include: Make ARRAY_SIZE() available in wine/test.h.
[wine.git] / dlls / d3d9 / tests / device.c
blobbd1890f45c55a55036eb514dc854261557de1982
1 /*
2 * Copyright (C) 2006 Ivan Gyurdiev
3 * Copyright (C) 2006 Vitaliy Margolen
4 * Copyright (C) 2006 Chris Robinson
5 * Copyright 2006-2008, 2010-2011, 2013 Stefan Dösinger for CodeWeavers
6 * Copyright 2005, 2006, 2007 Henri Verbeet
7 * Copyright 2013-2014 Henri Verbeet for CodeWeavers
8 * Copyright (C) 2008 Rico Schüller
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WINVER 0x0602 /* for CURSOR_SUPPRESSED */
26 #define COBJMACROS
27 #include <d3d9.h>
28 #include "wine/test.h"
30 struct vec3
32 float x, y, z;
35 #define CREATE_DEVICE_FULLSCREEN 0x01
36 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
37 #define CREATE_DEVICE_FPU_PRESERVE 0x04
38 #define CREATE_DEVICE_SWVP_ONLY 0x08
39 #define CREATE_DEVICE_MIXED_ONLY 0x10
40 #define CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT 0x20
41 #define CREATE_DEVICE_LOCKABLE_BACKBUFFER 0x40
43 struct device_desc
45 HWND device_window;
46 unsigned int width;
47 unsigned int height;
48 DWORD flags;
51 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
52 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
54 static DEVMODEW registry_mode;
56 static const DWORD simple_vs[] =
58 0xfffe0101, /* vs_1_1 */
59 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
60 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
61 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
62 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
63 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
64 0x0000ffff, /* end */
67 static const DWORD simple_ps[] =
69 0xffff0101, /* ps_1_1 */
70 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
71 0x00000042, 0xb00f0000, /* tex t0 */
72 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
73 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
74 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
75 0x0000ffff, /* end */
78 static int get_refcount(IUnknown *object)
80 IUnknown_AddRef( object );
81 return IUnknown_Release( object );
84 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
86 unsigned int element_count, i;
87 D3DVERTEXELEMENT9 *elements;
88 BOOL equal = TRUE;
89 HRESULT hr;
91 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
92 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
93 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
94 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
95 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
97 for (i = 0; i < element_count; ++i)
99 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
101 equal = FALSE;
102 break;
106 if (!equal)
108 for (i = 0; i < element_count; ++i)
110 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
111 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
112 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
116 HeapFree(GetProcessHeap(), 0, elements);
117 return equal;
120 /* try to make sure pending X events have been processed before continuing */
121 static void flush_events(void)
123 MSG msg;
124 int diff = 200;
125 int min_timeout = 100;
126 DWORD time = GetTickCount() + diff;
128 while (diff > 0)
130 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
131 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
132 diff = time - GetTickCount();
136 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
138 D3DPRESENT_PARAMETERS present_parameters = {0};
139 IDirect3DDevice9 *device;
140 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
142 present_parameters.BackBufferWidth = 640;
143 present_parameters.BackBufferHeight = 480;
144 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
145 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
146 present_parameters.hDeviceWindow = focus_window;
147 present_parameters.Windowed = TRUE;
148 present_parameters.EnableAutoDepthStencil = TRUE;
149 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
151 if (desc)
153 present_parameters.BackBufferWidth = desc->width;
154 present_parameters.BackBufferHeight = desc->height;
155 if (desc->flags & CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT)
156 present_parameters.BackBufferFormat = D3DFMT_UNKNOWN;
157 present_parameters.hDeviceWindow = desc->device_window;
158 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
159 if (desc->flags & CREATE_DEVICE_LOCKABLE_BACKBUFFER)
160 present_parameters.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
161 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
162 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
163 else if (desc->flags & CREATE_DEVICE_MIXED_ONLY)
164 behavior_flags = D3DCREATE_MIXED_VERTEXPROCESSING;
165 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
166 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
167 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
168 behavior_flags |= D3DCREATE_FPU_PRESERVE;
171 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
172 behavior_flags, &present_parameters, &device)))
173 return device;
175 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
176 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
177 behavior_flags, &present_parameters, &device)))
178 return device;
180 if (desc && (desc->flags & (CREATE_DEVICE_SWVP_ONLY | CREATE_DEVICE_MIXED_ONLY)))
181 return NULL;
182 behavior_flags = (behavior_flags
183 & ~(D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING))
184 | D3DCREATE_HARDWARE_VERTEXPROCESSING;
186 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
187 behavior_flags, &present_parameters, &device)))
188 return device;
190 return NULL;
193 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
195 D3DPRESENT_PARAMETERS present_parameters = {0};
197 present_parameters.BackBufferWidth = 640;
198 present_parameters.BackBufferHeight = 480;
199 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
200 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
201 present_parameters.hDeviceWindow = NULL;
202 present_parameters.Windowed = TRUE;
203 present_parameters.EnableAutoDepthStencil = TRUE;
204 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
206 if (desc)
208 present_parameters.BackBufferWidth = desc->width;
209 present_parameters.BackBufferHeight = desc->height;
210 present_parameters.hDeviceWindow = desc->device_window;
211 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
214 return IDirect3DDevice9_Reset(device, &present_parameters);
217 #define CHECK_CALL(r,c,d,rc) \
218 if (SUCCEEDED(r)) {\
219 int tmp1 = get_refcount( (IUnknown *)d ); \
220 int rc_new = rc; \
221 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
222 } else {\
223 trace("%s failed: %08x\n", c, r); \
226 #define CHECK_RELEASE(obj,d,rc) \
227 if (obj) { \
228 int tmp1, rc_new = rc; \
229 IUnknown_Release( (IUnknown*)obj ); \
230 tmp1 = get_refcount( (IUnknown *)d ); \
231 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
234 #define CHECK_REFCOUNT(obj,rc) \
236 int rc_new = rc; \
237 int count = get_refcount( (IUnknown *)obj ); \
238 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
241 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
243 int rc_new = rc; \
244 int count = IUnknown_Release( (IUnknown *)obj ); \
245 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
248 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
250 int rc_new = rc; \
251 int count = IUnknown_AddRef( (IUnknown *)obj ); \
252 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
255 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
257 void *container_ptr = (void *)0x1337c0d3; \
258 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
259 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
260 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
261 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
264 static void test_get_set_vertex_declaration(void)
266 IDirect3DVertexDeclaration9 *declaration, *tmp;
267 ULONG refcount, expected_refcount;
268 IDirect3DDevice9 *device;
269 IDirect3D9 *d3d;
270 HWND window;
271 HRESULT hr;
273 static const D3DVERTEXELEMENT9 simple_decl[] =
275 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
276 D3DDECL_END()
279 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
280 0, 0, 640, 480, NULL, NULL, NULL, NULL);
281 d3d = Direct3DCreate9(D3D_SDK_VERSION);
282 ok(!!d3d, "Failed to create a D3D object.\n");
283 if (!(device = create_device(d3d, window, NULL)))
285 skip("Failed to create a D3D device, skipping tests.\n");
286 goto done;
289 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
290 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
292 /* SetVertexDeclaration() should not touch the declaration's refcount. */
293 expected_refcount = get_refcount((IUnknown *)declaration);
294 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
295 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
296 refcount = get_refcount((IUnknown *)declaration);
297 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
299 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
300 tmp = NULL;
301 expected_refcount = refcount + 1;
302 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
303 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
304 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
305 refcount = get_refcount((IUnknown *)declaration);
306 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
307 IDirect3DVertexDeclaration9_Release(tmp);
309 IDirect3DVertexDeclaration9_Release(declaration);
310 refcount = IDirect3DDevice9_Release(device);
311 ok(!refcount, "Device has %u references left.\n", refcount);
312 done:
313 IDirect3D9_Release(d3d);
314 DestroyWindow(window);
317 static void test_get_declaration(void)
319 unsigned int element_count, expected_element_count;
320 IDirect3DVertexDeclaration9 *declaration;
321 D3DVERTEXELEMENT9 *elements;
322 IDirect3DDevice9 *device;
323 IDirect3D9 *d3d;
324 ULONG refcount;
325 HWND window;
326 HRESULT hr;
328 static const D3DVERTEXELEMENT9 simple_decl[] =
330 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
331 D3DDECL_END()
334 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
335 0, 0, 640, 480, NULL, NULL, NULL, NULL);
336 d3d = Direct3DCreate9(D3D_SDK_VERSION);
337 ok(!!d3d, "Failed to create a D3D object.\n");
338 if (!(device = create_device(d3d, window, NULL)))
340 skip("Failed to create a D3D device, skipping tests.\n");
341 goto done;
344 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
345 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
347 /* First test only getting the number of elements. */
348 element_count = 0x1337c0de;
349 expected_element_count = ARRAY_SIZE(simple_decl);
350 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
351 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
352 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
353 element_count, expected_element_count);
355 element_count = 0;
356 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
357 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
358 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
359 element_count, expected_element_count);
361 /* Also test the returned data. */
362 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
364 element_count = 0x1337c0de;
365 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
366 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
367 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
368 element_count, expected_element_count);
369 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
370 "Original and returned vertexdeclarations are not the same.\n");
372 memset(elements, 0, sizeof(simple_decl));
374 element_count = 0;
375 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
376 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
377 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
378 element_count, expected_element_count);
379 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
380 "Original and returned vertexdeclarations are not the same.\n");
382 HeapFree(GetProcessHeap(), 0, elements);
383 IDirect3DVertexDeclaration9_Release(declaration);
384 refcount = IDirect3DDevice9_Release(device);
385 ok(!refcount, "Device has %u references left.\n", refcount);
386 done:
387 IDirect3D9_Release(d3d);
388 DestroyWindow(window);
391 static void test_fvf_decl_conversion(void)
393 IDirect3DVertexDeclaration9 *default_decl;
394 IDirect3DVertexDeclaration9 *declaration;
395 IDirect3DDevice9 *device;
396 IDirect3D9 *d3d;
397 ULONG refcount;
398 unsigned int i;
399 HWND window;
400 HRESULT hr;
402 static const D3DVERTEXELEMENT9 default_elements[] =
404 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
405 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
406 D3DDECL_END()
408 /* Test conversions from vertex declaration to an FVF. For some reason
409 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
410 * forced to 0 - maybe this is configuration specific. */
411 static const struct
413 D3DVERTEXELEMENT9 elements[7];
414 DWORD fvf;
415 BOOL todo;
417 decl_to_fvf_tests[] =
419 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
420 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
421 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
422 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
423 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
424 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
425 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
426 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
427 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
428 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
429 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
430 /* No FVF mapping available. */
431 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
432 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
433 /* Try empty declaration. */
434 {{ D3DDECL_END()}, 0, FALSE},
435 /* Make sure textures of different sizes work. */
436 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
437 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
438 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
439 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
440 /* Make sure the TEXCOORD index works correctly - try several textures. */
443 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
444 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
445 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
446 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
447 D3DDECL_END(),
448 }, 0, FALSE,
450 /* Now try a combination test. */
453 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
454 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
455 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
456 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
457 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
458 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
459 D3DDECL_END(),
460 }, 0, FALSE,
463 /* Test conversions from FVF to a vertex declaration. These seem to always
464 * occur internally. A new declaration object is created if necessary. */
465 static const struct
467 DWORD fvf;
468 D3DVERTEXELEMENT9 elements[7];
470 fvf_to_decl_tests[] =
472 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
473 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
474 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
476 D3DFVF_XYZB5,
478 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
479 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
480 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
481 D3DDECL_END(),
485 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
487 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
488 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
489 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
490 D3DDECL_END(),
494 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
496 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
497 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
498 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
499 D3DDECL_END(),
503 D3DFVF_XYZB1,
505 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
506 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
507 D3DDECL_END(),
511 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
513 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
514 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
515 D3DDECL_END(),
519 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
521 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
522 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
523 D3DDECL_END(),
527 D3DFVF_XYZB2,
529 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
530 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
531 D3DDECL_END(),
535 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
537 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
538 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
539 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
540 D3DDECL_END(),
544 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
546 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
547 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
548 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
549 D3DDECL_END(),
553 D3DFVF_XYZB3,
555 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
556 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
557 D3DDECL_END(),
561 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
563 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
564 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
565 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
566 D3DDECL_END(),
570 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
572 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
573 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
574 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
575 D3DDECL_END(),
579 D3DFVF_XYZB4,
581 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
582 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
583 D3DDECL_END(),
587 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
589 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
590 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
591 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
592 D3DDECL_END(),
596 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
598 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
599 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
600 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
601 D3DDECL_END(),
604 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
605 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
606 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
607 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
608 /* Make sure textures of different sizes work. */
610 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
611 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
614 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
615 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
618 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
619 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
622 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
623 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
625 /* Make sure the TEXCOORD index works correctly - try several textures. */
627 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
628 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
630 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
631 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
632 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
633 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
634 D3DDECL_END(),
637 /* Now try a combination test. */
639 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
640 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
642 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
643 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
644 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
645 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
646 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
647 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
648 D3DDECL_END(),
653 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
654 0, 0, 640, 480, NULL, NULL, NULL, NULL);
655 d3d = Direct3DCreate9(D3D_SDK_VERSION);
656 ok(!!d3d, "Failed to create a D3D object.\n");
657 if (!(device = create_device(d3d, window, NULL)))
659 skip("Failed to create a D3D device, skipping tests.\n");
660 goto done;
663 for (i = 0; i < ARRAY_SIZE(decl_to_fvf_tests); ++i)
665 DWORD fvf = 0xdeadbeef;
666 HRESULT hr;
668 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
669 * back to 0. */
670 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
671 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
673 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
674 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
675 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
676 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
678 /* Check the FVF. */
679 hr = IDirect3DDevice9_GetFVF(device, &fvf);
680 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
682 todo_wine_if (decl_to_fvf_tests[i].todo)
683 ok(fvf == decl_to_fvf_tests[i].fvf,
684 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
685 i, fvf, decl_to_fvf_tests[i].fvf);
687 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
688 IDirect3DVertexDeclaration9_Release(declaration);
691 /* Create a default declaration and FVF that does not match any of the
692 * tests. */
693 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
694 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
696 for (i = 0; i < ARRAY_SIZE(fvf_to_decl_tests); ++i)
698 /* Set a default declaration to make sure it is changed. */
699 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
700 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
702 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
703 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
705 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
706 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
707 ok(!!declaration && declaration != default_decl,
708 "Test %u: Got unexpected declaration %p.\n", i, declaration);
709 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
710 "Test %u: Declaration does not match.\n", i);
711 IDirect3DVertexDeclaration9_Release(declaration);
714 /* Setting the FVF to 0 should result in no change to the default decl. */
715 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
716 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
717 hr = IDirect3DDevice9_SetFVF(device, 0);
718 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
719 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
720 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
721 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
722 IDirect3DVertexDeclaration9_Release(declaration);
724 IDirect3DVertexDeclaration9_Release(default_decl);
725 refcount = IDirect3DDevice9_Release(device);
726 ok(!refcount, "Device has %u references left.\n", refcount);
727 done:
728 IDirect3D9_Release(d3d);
729 DestroyWindow(window);
732 /* Check whether a declaration converted from FVF is shared.
733 * Check whether refcounts behave as expected. */
734 static void test_fvf_decl_management(void)
736 IDirect3DVertexDeclaration9 *declaration1;
737 IDirect3DVertexDeclaration9 *declaration2;
738 IDirect3DVertexDeclaration9 *declaration3;
739 IDirect3DVertexDeclaration9 *declaration4;
740 IDirect3DDevice9 *device;
741 IDirect3D9 *d3d;
742 ULONG refcount;
743 HWND window;
744 HRESULT hr;
746 static const D3DVERTEXELEMENT9 test_elements1[] =
747 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
748 static const D3DVERTEXELEMENT9 test_elements2[] =
749 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
751 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
752 0, 0, 640, 480, NULL, NULL, NULL, NULL);
753 d3d = Direct3DCreate9(D3D_SDK_VERSION);
754 ok(!!d3d, "Failed to create a D3D object.\n");
755 if (!(device = create_device(d3d, window, NULL)))
757 skip("Failed to create a D3D device, skipping tests.\n");
758 goto done;
761 /* Clear down any current vertex declaration. */
762 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
763 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
764 /* Conversion. */
765 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
766 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
767 /* Get converted decl (#1). */
768 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
769 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
770 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
771 /* Get converted decl again (#2). */
772 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
773 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
774 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
776 /* Conversion. */
777 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
778 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
779 /* Get converted decl (#3). */
780 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
781 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
782 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
783 /* The contents should correspond to the second conversion. */
784 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
785 /* Re-Check if the first decl was overwritten by the new Get(). */
786 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
788 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
789 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
790 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
791 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
792 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
794 refcount = get_refcount((IUnknown*)declaration1);
795 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
796 refcount = get_refcount((IUnknown*)declaration2);
797 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
798 refcount = get_refcount((IUnknown*)declaration3);
799 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
800 refcount = get_refcount((IUnknown*)declaration4);
801 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
803 IDirect3DVertexDeclaration9_Release(declaration4);
804 IDirect3DVertexDeclaration9_Release(declaration3);
805 IDirect3DVertexDeclaration9_Release(declaration2);
806 IDirect3DVertexDeclaration9_Release(declaration1);
808 refcount = IDirect3DDevice9_Release(device);
809 ok(!refcount, "Device has %u references left.\n", refcount);
810 done:
811 IDirect3D9_Release(d3d);
812 DestroyWindow(window);
815 static void test_vertex_declaration_alignment(void)
817 IDirect3DVertexDeclaration9 *declaration;
818 IDirect3DDevice9 *device;
819 IDirect3D9 *d3d;
820 unsigned int i;
821 ULONG refcount;
822 HWND window;
823 HRESULT hr;
825 static const struct
827 D3DVERTEXELEMENT9 elements[3];
828 HRESULT hr;
830 test_data[] =
834 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
835 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
836 D3DDECL_END(),
837 }, D3D_OK,
841 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
842 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
843 D3DDECL_END(),
844 }, E_FAIL,
848 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
849 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
850 D3DDECL_END(),
851 }, E_FAIL,
855 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
856 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
857 D3DDECL_END(),
858 }, E_FAIL,
862 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
863 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
864 D3DDECL_END(),
865 }, D3D_OK,
869 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
870 0, 0, 640, 480, NULL, NULL, NULL, NULL);
871 d3d = Direct3DCreate9(D3D_SDK_VERSION);
872 ok(!!d3d, "Failed to create a D3D object.\n");
873 if (!(device = create_device(d3d, window, NULL)))
875 skip("Failed to create a D3D device, skipping tests.\n");
876 goto done;
879 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
881 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
882 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
883 if (SUCCEEDED(hr))
884 IDirect3DVertexDeclaration9_Release(declaration);
887 refcount = IDirect3DDevice9_Release(device);
888 ok(!refcount, "Device has %u references left.\n", refcount);
889 done:
890 IDirect3D9_Release(d3d);
891 DestroyWindow(window);
894 static void test_unused_declaration_type(void)
896 IDirect3DVertexDeclaration9 *declaration;
897 IDirect3DDevice9 *device;
898 IDirect3D9 *d3d;
899 unsigned int i;
900 ULONG refcount;
901 HWND window;
902 HRESULT hr;
904 static const D3DVERTEXELEMENT9 test_elements[][3] =
907 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
908 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
909 D3DDECL_END(),
912 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
913 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
914 D3DDECL_END(),
917 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
918 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
919 D3DDECL_END(),
922 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
923 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
924 D3DDECL_END(),
927 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
928 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
929 D3DDECL_END(),
932 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
933 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
934 D3DDECL_END(),
937 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
938 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
939 D3DDECL_END(),
943 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
944 0, 0, 640, 480, NULL, NULL, NULL, NULL);
945 d3d = Direct3DCreate9(D3D_SDK_VERSION);
946 ok(!!d3d, "Failed to create a D3D object.\n");
947 if (!(device = create_device(d3d, window, NULL)))
949 skip("Failed to create a D3D device, skipping tests.\n");
950 goto done;
953 for (i = 0; i < ARRAY_SIZE(test_elements); ++i)
955 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
956 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
959 refcount = IDirect3DDevice9_Release(device);
960 ok(!refcount, "Device has %u references left.\n", refcount);
961 done:
962 IDirect3D9_Release(d3d);
963 DestroyWindow(window);
966 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
968 IDirect3DBaseTexture9* texture = NULL;
969 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
970 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
972 if (SUCCEEDED(hr)) {
973 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
974 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
975 } else
976 trace("CreateTexture failed: %08x\n", hr);
978 if (texture) IDirect3DBaseTexture9_Release( texture );
981 static void test_mipmap_levels(void)
983 IDirect3DDevice9 *device;
984 IDirect3D9 *d3d;
985 ULONG refcount;
986 HWND window;
988 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
989 0, 0, 640, 480, NULL, NULL, NULL, NULL);
990 ok(!!window, "Failed to create a window.\n");
991 d3d = Direct3DCreate9(D3D_SDK_VERSION);
992 ok(!!d3d, "Failed to create a D3D object.\n");
993 if (!(device = create_device(d3d, window, NULL)))
995 skip("Failed to create a 3D device, skipping test.\n");
996 goto cleanup;
999 check_mipmap_levels(device, 32, 32, 6);
1000 check_mipmap_levels(device, 256, 1, 9);
1001 check_mipmap_levels(device, 1, 256, 9);
1002 check_mipmap_levels(device, 1, 1, 1);
1004 refcount = IDirect3DDevice9_Release(device);
1005 ok(!refcount, "Device has %u references left.\n", refcount);
1006 cleanup:
1007 IDirect3D9_Release(d3d);
1008 DestroyWindow(window);
1011 static void test_checkdevicemultisampletype(void)
1013 DWORD quality_levels;
1014 IDirect3D9 *d3d;
1015 HWND window;
1016 HRESULT hr;
1018 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1019 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1020 ok(!!window, "Failed to create a window.\n");
1021 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1022 ok(!!d3d, "Failed to create a D3D object.\n");
1024 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1025 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL) == D3DERR_NOTAVAILABLE)
1027 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
1028 goto cleanup;
1031 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1032 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE, NULL);
1033 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1034 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1035 65536, TRUE, D3DMULTISAMPLE_NONE, NULL);
1036 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1038 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1039 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, NULL);
1040 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1042 quality_levels = 0;
1043 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1044 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1045 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1046 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1047 quality_levels = 0;
1048 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1049 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1050 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1051 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1053 quality_levels = 0;
1054 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1055 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, NULL);
1056 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1057 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1058 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels);
1059 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1060 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1062 quality_levels = 0;
1063 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1064 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1065 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1066 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1067 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels);
1068 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1069 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1071 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1072 quality_levels = 0;
1073 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1074 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1075 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1076 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1077 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, &quality_levels);
1078 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1079 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1081 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1082 D3DFMT_X8R8G8B8, TRUE, 65536, NULL);
1083 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1085 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1086 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1087 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1089 cleanup:
1090 IDirect3D9_Release(d3d);
1091 DestroyWindow(window);
1094 static void test_invalid_multisample(void)
1096 IDirect3DDevice9 *device;
1097 IDirect3DSurface9 *rt;
1098 DWORD quality_levels;
1099 IDirect3D9 *d3d;
1100 BOOL available;
1101 ULONG refcount;
1102 HWND window;
1103 HRESULT hr;
1105 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1106 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1107 ok(!!window, "Failed to create a window.\n");
1108 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1109 ok(!!d3d, "Failed to create a D3D object.\n");
1111 if (!(device = create_device(d3d, window, NULL)))
1113 skip("Failed to create a 3D device, skipping test.\n");
1114 goto cleanup;
1117 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1118 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels));
1119 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1120 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, 0, FALSE, &rt, NULL);
1121 if (available)
1123 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1124 IDirect3DSurface9_Release(rt);
1125 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1126 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, quality_levels, FALSE, &rt, NULL);
1127 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1129 else
1131 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1134 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1135 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels));
1136 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1137 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &rt, NULL);
1138 if (available)
1140 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1141 IDirect3DSurface9_Release(rt);
1142 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1143 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels, FALSE, &rt, NULL);
1144 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1146 else
1148 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1151 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1152 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1153 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1154 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1155 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1156 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, 0, FALSE, &rt, NULL);
1157 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1159 refcount = IDirect3DDevice9_Release(device);
1160 ok(!refcount, "Device has %u references left.\n", refcount);
1161 cleanup:
1162 IDirect3D9_Release(d3d);
1163 DestroyWindow(window);
1166 static void test_swapchain(void)
1168 IDirect3DSwapChain9 *swapchain0;
1169 IDirect3DSwapChain9 *swapchain1;
1170 IDirect3DSwapChain9 *swapchain2;
1171 IDirect3DSwapChain9 *swapchain3;
1172 IDirect3DSwapChain9 *swapchainX;
1173 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1174 D3DPRESENT_PARAMETERS d3dpp;
1175 IDirect3DDevice9 *device;
1176 IDirect3D9 *d3d;
1177 ULONG refcount;
1178 HWND window, window2;
1179 HRESULT hr;
1180 struct device_desc device_desc;
1182 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1183 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1184 ok(!!window, "Failed to create a window.\n");
1185 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1186 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1187 ok(!!window2, "Failed to create a window.\n");
1188 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1189 ok(!!d3d, "Failed to create a D3D object.\n");
1190 if (!(device = create_device(d3d, window, NULL)))
1192 skip("Failed to create a 3D device, skipping test.\n");
1193 goto cleanup;
1196 /* Get the implicit swapchain */
1197 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1198 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1199 /* Check if the back buffer count was modified */
1200 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1201 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1202 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1203 IDirect3DSwapChain9_Release(swapchain0);
1205 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1206 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1207 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1208 backbuffer = (void *)0xdeadbeef;
1209 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1210 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1211 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1212 backbuffer = (void *)0xdeadbeef;
1213 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1214 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1215 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1217 /* Check if there is a back buffer */
1218 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1219 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1220 ok(backbuffer != NULL, "The back buffer is NULL\n");
1221 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1223 /* The back buffer type value is ignored. */
1224 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1225 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1226 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1227 IDirect3DSurface9_Release(stereo_buffer);
1228 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1229 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1230 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1231 IDirect3DSurface9_Release(stereo_buffer);
1232 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1233 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1234 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1235 IDirect3DSurface9_Release(stereo_buffer);
1237 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1238 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1239 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1240 IDirect3DSurface9_Release(stereo_buffer);
1241 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1242 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1243 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1244 IDirect3DSurface9_Release(stereo_buffer);
1245 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1246 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1247 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1248 IDirect3DSurface9_Release(stereo_buffer);
1250 /* Try to get a nonexistent swapchain */
1251 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1252 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1253 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1254 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1256 /* Create a bunch of swapchains */
1257 d3dpp.BackBufferCount = 0;
1258 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1259 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1260 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1262 d3dpp.BackBufferCount = 1;
1263 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1264 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1266 d3dpp.BackBufferCount = 2;
1267 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1268 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1269 if(SUCCEEDED(hr)) {
1270 /* Swapchain 3, created with backbuffercount 2 */
1271 backbuffer = (void *) 0xdeadbeef;
1272 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1273 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1274 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1275 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1277 backbuffer = (void *) 0xdeadbeef;
1278 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1279 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1280 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1281 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1283 backbuffer = (void *) 0xdeadbeef;
1284 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1285 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1286 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1287 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1289 backbuffer = (void *) 0xdeadbeef;
1290 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1291 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1292 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1293 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1296 /* Check the back buffers of the swapchains */
1297 /* Swapchain 1, created with backbuffercount 0 */
1298 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1299 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1300 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1301 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1303 backbuffer = (void *) 0xdeadbeef;
1304 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1305 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1306 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1307 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1309 /* Swapchain 2 - created with backbuffercount 1 */
1310 backbuffer = (void *) 0xdeadbeef;
1311 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1312 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1313 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1314 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1316 backbuffer = (void *) 0xdeadbeef;
1317 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1318 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1319 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1320 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1322 backbuffer = (void *) 0xdeadbeef;
1323 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1324 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1325 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1326 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1328 /* Try getSwapChain on a manually created swapchain
1329 * it should fail, apparently GetSwapChain only returns implicit swapchains
1331 swapchainX = (void *) 0xdeadbeef;
1332 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1333 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1334 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1335 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1337 IDirect3DSwapChain9_Release(swapchain3);
1338 IDirect3DSwapChain9_Release(swapchain2);
1339 IDirect3DSwapChain9_Release(swapchain1);
1341 d3dpp.Windowed = FALSE;
1342 d3dpp.hDeviceWindow = window;
1343 d3dpp.BackBufferCount = 1;
1344 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1345 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1346 d3dpp.hDeviceWindow = window2;
1347 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1348 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1350 device_desc.width = registry_mode.dmPelsWidth;
1351 device_desc.height = registry_mode.dmPelsHeight;
1352 device_desc.device_window = window;
1353 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1354 hr = reset_device(device, &device_desc);
1355 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1357 d3dpp.hDeviceWindow = window;
1358 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1359 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1360 d3dpp.hDeviceWindow = window2;
1361 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1362 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1363 d3dpp.Windowed = TRUE;
1364 d3dpp.hDeviceWindow = window;
1365 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1366 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1367 d3dpp.hDeviceWindow = window2;
1368 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1369 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1371 refcount = IDirect3DDevice9_Release(device);
1372 ok(!refcount, "Device has %u references left.\n", refcount);
1373 cleanup:
1374 IDirect3D9_Release(d3d);
1375 DestroyWindow(window2);
1376 DestroyWindow(window);
1379 static void test_refcount(void)
1381 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1382 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1383 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1384 IDirect3DVertexShader9 *pVertexShader = NULL;
1385 IDirect3DPixelShader9 *pPixelShader = NULL;
1386 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1387 IDirect3DTexture9 *pTexture = NULL;
1388 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1389 IDirect3DVolume9 *pVolumeLevel = NULL;
1390 IDirect3DSurface9 *pStencilSurface = NULL;
1391 IDirect3DSurface9 *pOffscreenSurface = NULL;
1392 IDirect3DSurface9 *pRenderTarget = NULL;
1393 IDirect3DSurface9 *pRenderTarget2 = NULL;
1394 IDirect3DSurface9 *pRenderTarget3 = NULL;
1395 IDirect3DSurface9 *pTextureLevel = NULL;
1396 IDirect3DSurface9 *pBackBuffer = NULL;
1397 IDirect3DStateBlock9 *pStateBlock = NULL;
1398 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1399 IDirect3DSwapChain9 *pSwapChain = NULL;
1400 IDirect3DQuery9 *pQuery = NULL;
1401 D3DPRESENT_PARAMETERS d3dpp;
1402 IDirect3DDevice9 *device;
1403 ULONG refcount = 0, tmp;
1404 IDirect3D9 *d3d, *d3d2;
1405 HWND window;
1406 HRESULT hr;
1408 D3DVERTEXELEMENT9 decl[] =
1410 D3DDECL_END()
1413 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1414 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1415 ok(!!window, "Failed to create a window.\n");
1416 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1417 ok(!!d3d, "Failed to create a D3D object.\n");
1419 CHECK_REFCOUNT(d3d, 1);
1421 if (!(device = create_device(d3d, window, NULL)))
1423 skip("Failed to create a 3D device, skipping test.\n");
1424 goto cleanup;
1427 refcount = get_refcount((IUnknown *)device);
1428 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1430 CHECK_REFCOUNT(d3d, 2);
1432 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1433 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1435 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1436 CHECK_REFCOUNT(d3d, 3);
1437 CHECK_RELEASE_REFCOUNT(d3d, 2);
1440 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1441 * - the container is the device OR swapchain
1442 * - they hold a reference to the device
1443 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1444 * - they are not freed if refcount reaches 0.
1445 * - the refcount is not forwarded to the container.
1447 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1448 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1449 if (pSwapChain)
1451 CHECK_REFCOUNT(pSwapChain, 1);
1453 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1454 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1455 CHECK_REFCOUNT(pSwapChain, 1);
1456 if (pRenderTarget)
1458 CHECK_SURFACE_CONTAINER(pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1459 CHECK_REFCOUNT(pRenderTarget, 1);
1461 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1462 CHECK_REFCOUNT(device, refcount);
1463 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1464 CHECK_REFCOUNT(device, refcount);
1466 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1467 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1468 CHECK_REFCOUNT(pRenderTarget, 2);
1469 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1470 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1471 CHECK_REFCOUNT(device, --refcount);
1473 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1474 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1475 CHECK_REFCOUNT(device, ++refcount);
1476 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1477 CHECK_REFCOUNT(device, --refcount);
1478 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1479 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1482 /* Render target and back buffer are identical. */
1483 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1484 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1485 if (pBackBuffer)
1487 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1488 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1489 pRenderTarget, pBackBuffer);
1490 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1491 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1492 pBackBuffer = NULL;
1494 CHECK_REFCOUNT(device, --refcount);
1496 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1497 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1498 CHECK_REFCOUNT(pSwapChain, 1);
1499 if (pStencilSurface)
1501 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1502 CHECK_REFCOUNT( pStencilSurface, 1);
1504 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1505 CHECK_REFCOUNT(device, refcount);
1506 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1507 CHECK_REFCOUNT(device, refcount);
1509 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1510 CHECK_REFCOUNT(device, --refcount);
1512 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1513 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1514 CHECK_REFCOUNT(device, ++refcount);
1515 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1516 CHECK_REFCOUNT(device, --refcount);
1517 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1518 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1519 pStencilSurface = NULL;
1522 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1523 CHECK_REFCOUNT(device, --refcount);
1524 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1525 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1527 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1528 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1529 CHECK_REFCOUNT(device, ++refcount);
1530 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1531 CHECK_REFCOUNT(device, --refcount);
1532 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1533 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1534 pSwapChain = NULL;
1537 /* Buffers */
1538 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1539 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1540 if(pIndexBuffer)
1542 tmp = get_refcount((IUnknown *)pIndexBuffer);
1544 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1545 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1546 hr = IDirect3DDevice9_SetIndices(device, NULL);
1547 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1550 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1551 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1552 if(pVertexBuffer)
1554 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1555 UINT offset = ~0;
1556 UINT stride = ~0;
1558 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1560 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1561 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1562 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1563 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1565 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1566 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1567 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1568 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1569 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1571 /* Shaders */
1572 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1573 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1574 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1575 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1576 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1577 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1578 /* Textures */
1579 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1580 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1581 if (pTexture)
1583 tmp = get_refcount( (IUnknown *)pTexture );
1585 /* SetTexture should not increase refcounts */
1586 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1587 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1588 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1589 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1591 /* This should not increment device refcount */
1592 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1593 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1594 /* But should increment texture's refcount */
1595 CHECK_REFCOUNT( pTexture, tmp+1 );
1596 /* Because the texture and surface refcount are identical */
1597 if (pTextureLevel)
1599 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1600 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1601 CHECK_REFCOUNT ( pTexture , tmp+2 );
1602 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1603 CHECK_REFCOUNT ( pTexture , tmp+1 );
1604 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1605 CHECK_REFCOUNT ( pTextureLevel, tmp );
1608 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1609 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1610 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1611 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1612 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1613 if (pVolumeTexture)
1615 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1617 /* This should not increment device refcount */
1618 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1619 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1620 /* But should increment volume texture's refcount */
1621 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1622 /* Because the volume texture and volume refcount are identical */
1623 if (pVolumeLevel)
1625 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1626 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1627 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1628 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1629 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1630 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1631 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1634 /* Surfaces */
1635 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1636 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1637 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1638 CHECK_REFCOUNT( pStencilSurface, 1 );
1639 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1640 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1641 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1642 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1643 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1644 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1645 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1646 CHECK_REFCOUNT( pRenderTarget3, 1 );
1647 /* Misc */
1648 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1649 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1651 memset(&d3dpp, 0, sizeof(d3dpp));
1652 d3dpp.Windowed = TRUE;
1653 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1654 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1655 d3dpp.EnableAutoDepthStencil = TRUE;
1656 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1657 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1658 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1659 if (pSwapChain)
1661 /* check implicit back buffer */
1662 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1663 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1664 CHECK_REFCOUNT(pSwapChain, 1);
1665 if (pBackBuffer)
1667 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1668 CHECK_REFCOUNT(pBackBuffer, 1);
1669 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1670 CHECK_REFCOUNT(device, --refcount);
1672 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1673 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1674 CHECK_REFCOUNT(device, ++refcount);
1675 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1676 CHECK_REFCOUNT(device, --refcount);
1677 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1678 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1679 pBackBuffer = NULL;
1681 CHECK_REFCOUNT(pSwapChain, 1);
1683 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1684 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1686 hr = IDirect3DDevice9_BeginStateBlock(device);
1687 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1688 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1689 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1691 /* The implicit render target is not freed if refcount reaches 0.
1692 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1693 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1694 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1695 if (pRenderTarget2)
1697 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1698 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1699 pRenderTarget, pRenderTarget2);
1700 CHECK_REFCOUNT(device, --refcount);
1701 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1702 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1703 pRenderTarget2 = NULL;
1705 pRenderTarget = NULL;
1707 cleanup:
1708 CHECK_RELEASE(device, device, --refcount);
1710 /* Buffers */
1711 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1712 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1713 /* Shaders */
1714 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1715 CHECK_RELEASE(pVertexShader, device, --refcount);
1716 CHECK_RELEASE(pPixelShader, device, --refcount);
1717 /* Textures */
1718 CHECK_RELEASE(pTextureLevel, device, --refcount);
1719 CHECK_RELEASE(pCubeTexture, device, --refcount);
1720 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1721 /* Surfaces */
1722 CHECK_RELEASE(pStencilSurface, device, --refcount);
1723 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1724 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1725 /* Misc */
1726 CHECK_RELEASE(pStateBlock, device, --refcount);
1727 CHECK_RELEASE(pSwapChain, device, --refcount);
1728 CHECK_RELEASE(pQuery, device, --refcount);
1729 /* This will destroy device - cannot check the refcount here */
1730 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1731 CHECK_RELEASE_REFCOUNT(d3d, 0);
1732 DestroyWindow(window);
1735 static void test_cursor(void)
1737 IDirect3DSurface9 *cursor = NULL;
1738 IDirect3DDevice9 *device;
1739 CURSORINFO info;
1740 IDirect3D9 *d3d;
1741 ULONG refcount;
1742 HCURSOR cur;
1743 HWND window;
1744 HRESULT hr;
1745 BOOL ret;
1747 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1748 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1749 ok(!!window, "Failed to create a window.\n");
1751 ret = SetCursorPos(50, 50);
1752 ok(ret, "Failed to set cursor position.\n");
1753 flush_events();
1754 memset(&info, 0, sizeof(info));
1755 info.cbSize = sizeof(info);
1756 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1757 cur = info.hCursor;
1759 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1760 ok(!!d3d, "Failed to create a D3D object.\n");
1761 if (!(device = create_device(d3d, window, NULL)))
1763 skip("Failed to create a 3D device, skipping test.\n");
1764 goto cleanup;
1767 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1768 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1769 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1771 /* Initially hidden */
1772 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1773 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1775 /* Not enabled without a surface*/
1776 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1777 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1779 /* Fails */
1780 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1781 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1783 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1784 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1786 IDirect3DSurface9_Release(cursor);
1788 memset(&info, 0, sizeof(info));
1789 info.cbSize = sizeof(info);
1790 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1791 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1792 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1794 /* Still hidden */
1795 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1796 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1798 /* Enabled now*/
1799 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1800 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1802 memset(&info, 0, sizeof(info));
1803 info.cbSize = sizeof(info);
1804 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1805 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1806 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1808 refcount = IDirect3DDevice9_Release(device);
1809 ok(!refcount, "Device has %u references left.\n", refcount);
1810 cleanup:
1811 IDirect3D9_Release(d3d);
1812 DestroyWindow(window);
1815 static void test_reset(void)
1817 HRESULT hr;
1818 RECT winrect, client_rect;
1819 D3DPRESENT_PARAMETERS d3dpp;
1820 D3DDISPLAYMODE d3ddm, d3ddm2;
1821 D3DVIEWPORT9 vp;
1822 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1823 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1824 IDirect3DSurface9 *surface;
1825 IDirect3DTexture9 *texture;
1826 IDirect3DVertexShader9 *shader;
1827 UINT i, adapter_mode_count;
1828 D3DLOCKED_RECT lockrect;
1829 IDirect3DDevice9 *device1 = NULL;
1830 IDirect3DDevice9 *device2 = NULL;
1831 IDirect3DSwapChain9 *swapchain;
1832 struct device_desc device_desc;
1833 DEVMODEW devmode;
1834 IDirect3D9 *d3d;
1835 D3DCAPS9 caps;
1836 DWORD value;
1837 HWND hwnd;
1838 LONG ret;
1839 struct
1841 UINT w;
1842 UINT h;
1843 } *modes = NULL;
1844 UINT mode_count = 0;
1846 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1847 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1848 ok(!!hwnd, "Failed to create a window.\n");
1849 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1850 ok(!!d3d, "Failed to create a D3D object.\n");
1852 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1853 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1854 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1855 for(i = 0; i < adapter_mode_count; ++i)
1857 UINT j;
1858 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1859 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1860 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1862 for (j = 0; j < mode_count; ++j)
1864 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1865 break;
1867 if (j == mode_count)
1869 modes[j].w = d3ddm2.Width;
1870 modes[j].h = d3ddm2.Height;
1871 ++mode_count;
1874 /* We use them as invalid modes */
1875 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1876 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1877 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1878 d3ddm2.Width, d3ddm2.Height);
1879 goto cleanup;
1883 if (mode_count < 2)
1885 skip("Less than 2 modes supported, skipping mode tests\n");
1886 goto cleanup;
1889 i = 0;
1890 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1892 device_desc.width = modes[i].w;
1893 device_desc.height = modes[i].h;
1894 device_desc.device_window = hwnd;
1895 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1896 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1898 skip("Failed to create a D3D device, skipping tests.\n");
1899 goto cleanup;
1901 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1902 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1904 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1905 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1907 width = GetSystemMetrics(SM_CXSCREEN);
1908 height = GetSystemMetrics(SM_CYSCREEN);
1909 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1910 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1912 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1913 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1914 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1915 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1916 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1917 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1918 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1919 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1921 i = 1;
1922 vp.X = 10;
1923 vp.Y = 20;
1924 vp.MinZ = 2;
1925 vp.MaxZ = 3;
1926 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1927 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1929 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1930 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1931 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1932 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1933 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1935 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1936 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1937 d3dpp.Windowed = FALSE;
1938 d3dpp.BackBufferWidth = modes[i].w;
1939 d3dpp.BackBufferHeight = modes[i].h;
1940 d3dpp.BackBufferFormat = d3ddm.Format;
1941 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1942 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1943 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1944 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1946 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1947 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1948 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1950 ZeroMemory(&vp, sizeof(vp));
1951 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1952 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1953 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1954 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1955 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1956 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1957 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1958 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1960 width = GetSystemMetrics(SM_CXSCREEN);
1961 height = GetSystemMetrics(SM_CYSCREEN);
1962 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1963 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1965 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1966 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1967 memset(&d3dpp, 0, sizeof(d3dpp));
1968 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1969 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1970 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1971 d3dpp.BackBufferWidth, modes[i].w);
1972 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1973 d3dpp.BackBufferHeight, modes[i].h);
1974 IDirect3DSwapChain9_Release(swapchain);
1976 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1977 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1978 d3dpp.Windowed = TRUE;
1979 d3dpp.BackBufferWidth = 400;
1980 d3dpp.BackBufferHeight = 300;
1981 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1982 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1983 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1984 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1985 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1987 width = GetSystemMetrics(SM_CXSCREEN);
1988 height = GetSystemMetrics(SM_CYSCREEN);
1989 ok(width == orig_width, "Screen width is %d\n", width);
1990 ok(height == orig_height, "Screen height is %d\n", height);
1992 ZeroMemory(&vp, sizeof(vp));
1993 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1994 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1995 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1996 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1997 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1998 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1999 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2000 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2002 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2003 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2004 memset(&d3dpp, 0, sizeof(d3dpp));
2005 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2006 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2007 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2008 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2009 IDirect3DSwapChain9_Release(swapchain);
2011 memset(&devmode, 0, sizeof(devmode));
2012 devmode.dmSize = sizeof(devmode);
2013 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2014 devmode.dmPelsWidth = modes[1].w;
2015 devmode.dmPelsHeight = modes[1].h;
2016 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2017 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2018 width = GetSystemMetrics(SM_CXSCREEN);
2019 height = GetSystemMetrics(SM_CYSCREEN);
2020 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2021 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2023 d3dpp.BackBufferWidth = 500;
2024 d3dpp.BackBufferHeight = 400;
2025 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
2026 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2027 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed, hr %#x.\n", hr);
2028 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2029 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x.\n", hr);
2031 width = GetSystemMetrics(SM_CXSCREEN);
2032 height = GetSystemMetrics(SM_CYSCREEN);
2033 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2034 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2036 ZeroMemory(&vp, sizeof(vp));
2037 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2038 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed, hr %#x.\n", hr);
2039 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
2040 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
2041 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
2042 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
2043 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
2044 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
2046 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2047 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2048 memset(&d3dpp, 0, sizeof(d3dpp));
2049 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2050 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2051 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2052 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2053 IDirect3DSwapChain9_Release(swapchain);
2055 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2056 devmode.dmPelsWidth = orig_width;
2057 devmode.dmPelsHeight = orig_height;
2058 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2059 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2060 width = GetSystemMetrics(SM_CXSCREEN);
2061 height = GetSystemMetrics(SM_CYSCREEN);
2062 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
2063 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
2065 SetRect(&winrect, 0, 0, 200, 150);
2066 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
2067 ok(SetWindowPos(hwnd, NULL, 0, 0,
2068 winrect.right-winrect.left,
2069 winrect.bottom-winrect.top,
2070 SWP_NOMOVE|SWP_NOZORDER),
2071 "SetWindowPos failed\n");
2073 /* Windows 10 gives us a different size than we requested with some DPI scaling settings (e.g. 172%). */
2074 GetClientRect(hwnd, &client_rect);
2076 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2077 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2078 d3dpp.Windowed = TRUE;
2079 d3dpp.BackBufferWidth = 0;
2080 d3dpp.BackBufferHeight = 0;
2081 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
2082 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2083 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2084 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2085 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2087 ok(d3dpp.BackBufferWidth == client_rect.right, "Got unexpected BackBufferWidth %u, expected %d.\n",
2088 d3dpp.BackBufferWidth, client_rect.right);
2089 ok(d3dpp.BackBufferHeight == client_rect.bottom, "Got unexpected BackBufferHeight %u, expected %d.\n",
2090 d3dpp.BackBufferHeight, client_rect.bottom);
2091 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2092 d3dpp.BackBufferFormat, d3ddm.Format);
2093 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2094 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2095 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2096 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2097 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
2098 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2099 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2100 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2101 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2102 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2103 d3dpp.FullScreen_RefreshRateInHz);
2104 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2106 ZeroMemory(&vp, sizeof(vp));
2107 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2108 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
2109 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
2110 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
2111 ok(vp.Width == client_rect.right, "D3DVIEWPORT->Width = %d, expected %d\n",
2112 vp.Width, client_rect.right);
2113 ok(vp.Height == client_rect.bottom, "D3DVIEWPORT->Height = %d, expected %d\n",
2114 vp.Height, client_rect.bottom);
2115 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2116 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2118 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2119 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2120 memset(&d3dpp, 0, sizeof(d3dpp));
2121 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2122 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2123 ok(d3dpp.BackBufferWidth == client_rect.right,
2124 "Got unexpected BackBufferWidth %u, expected %d.\n", d3dpp.BackBufferWidth, client_rect.right);
2125 ok(d3dpp.BackBufferHeight == client_rect.bottom,
2126 "Got unexpected BackBufferHeight %u, expected %d.\n", d3dpp.BackBufferHeight, client_rect.bottom);
2127 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2128 d3dpp.BackBufferFormat, d3ddm.Format);
2129 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2130 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2131 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2132 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2133 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
2134 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2135 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2136 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2137 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2138 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2139 d3dpp.FullScreen_RefreshRateInHz);
2140 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2141 IDirect3DSwapChain9_Release(swapchain);
2143 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2144 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2145 d3dpp.Windowed = TRUE;
2146 d3dpp.BackBufferWidth = 400;
2147 d3dpp.BackBufferHeight = 300;
2149 /* _Reset fails if there is a resource in the default pool */
2150 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
2151 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2152 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2153 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2154 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2155 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2156 IDirect3DSurface9_Release(surface);
2157 /* Reset again to get the device out of the lost state */
2158 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2159 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2160 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2161 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2163 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
2165 IDirect3DVolumeTexture9 *volume_texture;
2167 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
2168 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
2169 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
2170 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2171 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2172 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2173 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
2174 hr, D3DERR_DEVICENOTRESET);
2175 IDirect3DVolumeTexture9_Release(volume_texture);
2176 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2177 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
2178 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2179 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2181 else
2183 skip("Volume textures not supported.\n");
2186 /* Scratch, sysmem and managed pools are fine */
2187 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2188 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2189 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2190 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2191 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2192 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2193 IDirect3DSurface9_Release(surface);
2195 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2196 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2197 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2198 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2199 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2200 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2201 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2202 IDirect3DSurface9_Release(surface);
2204 /* The depth stencil should get reset to the auto depth stencil when present. */
2205 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2206 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2208 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2209 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2210 ok(surface == NULL, "Depth stencil should be NULL\n");
2212 d3dpp.EnableAutoDepthStencil = TRUE;
2213 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2214 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2215 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2217 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2218 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2219 ok(surface != NULL, "Depth stencil should not be NULL\n");
2220 if (surface) IDirect3DSurface9_Release(surface);
2222 d3dpp.EnableAutoDepthStencil = FALSE;
2223 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2224 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2226 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2227 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2228 ok(surface == NULL, "Depth stencil should be NULL\n");
2230 /* Will a sysmem or scratch survive while locked */
2231 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2232 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2233 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2234 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2235 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2236 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2237 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2238 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2239 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2240 IDirect3DSurface9_UnlockRect(surface);
2241 IDirect3DSurface9_Release(surface);
2243 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2244 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2245 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2246 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2247 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2248 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2249 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2250 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2251 IDirect3DSurface9_UnlockRect(surface);
2252 IDirect3DSurface9_Release(surface);
2254 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2255 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2256 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2257 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2258 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2259 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2260 IDirect3DTexture9_Release(texture);
2262 /* A reference held to an implicit surface causes failures as well */
2263 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2264 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2265 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2266 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2267 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2268 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2269 IDirect3DSurface9_Release(surface);
2270 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2271 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2272 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2273 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2275 /* Shaders are fine as well */
2276 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2277 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2278 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2279 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2280 IDirect3DVertexShader9_Release(shader);
2282 /* Try setting invalid modes */
2283 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2284 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2285 d3dpp.Windowed = FALSE;
2286 d3dpp.BackBufferWidth = 32;
2287 d3dpp.BackBufferHeight = 32;
2288 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2289 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2290 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2291 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2293 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2294 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2295 d3dpp.Windowed = FALSE;
2296 d3dpp.BackBufferWidth = 801;
2297 d3dpp.BackBufferHeight = 600;
2298 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2299 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2300 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2301 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2303 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2304 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2305 d3dpp.Windowed = FALSE;
2306 d3dpp.BackBufferWidth = 0;
2307 d3dpp.BackBufferHeight = 0;
2308 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2309 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2310 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2311 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2313 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2315 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2316 d3dpp.Windowed = TRUE;
2317 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2318 d3dpp.BackBufferFormat = d3ddm.Format;
2319 d3dpp.EnableAutoDepthStencil = FALSE;
2320 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2322 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2323 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2325 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2326 goto cleanup;
2329 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2330 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2332 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2333 d3dpp.Windowed = TRUE;
2334 d3dpp.BackBufferWidth = 400;
2335 d3dpp.BackBufferHeight = 300;
2336 d3dpp.EnableAutoDepthStencil = TRUE;
2337 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2339 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2340 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2342 if (FAILED(hr)) goto cleanup;
2344 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2345 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2346 ok(surface != NULL, "Depth stencil should not be NULL\n");
2347 if (surface) IDirect3DSurface9_Release(surface);
2349 cleanup:
2350 HeapFree(GetProcessHeap(), 0, modes);
2351 if (device2)
2353 UINT refcount = IDirect3DDevice9_Release(device2);
2354 ok(!refcount, "Device has %u references left.\n", refcount);
2356 if (device1)
2358 UINT refcount = IDirect3DDevice9_Release(device1);
2359 ok(!refcount, "Device has %u references left.\n", refcount);
2361 IDirect3D9_Release(d3d);
2362 DestroyWindow(hwnd);
2365 /* Test adapter display modes */
2366 static void test_display_modes(void)
2368 D3DDISPLAYMODE dmode;
2369 IDirect3D9 *d3d;
2371 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2372 ok(!!d3d, "Failed to create a D3D object.\n");
2374 #define TEST_FMT(x,r) do { \
2375 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2376 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2377 } while(0)
2379 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2380 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2381 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2382 /* D3DFMT_R5G6B5 */
2383 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2384 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2385 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2386 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2387 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2388 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2389 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2390 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2391 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2392 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2393 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2394 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2396 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2397 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2399 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2400 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2401 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2403 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2404 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2405 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2406 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2407 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2408 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2410 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2411 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2412 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2413 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2414 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2415 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2416 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2417 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2418 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2419 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2421 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2422 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2423 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2424 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2425 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2426 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2427 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2428 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2429 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2430 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2432 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2433 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2434 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2435 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2436 /* Floating point formats */
2437 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2438 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2439 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2441 /* IEEE formats */
2442 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2443 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2444 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2446 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2448 TEST_FMT(0, D3DERR_INVALIDCALL);
2450 IDirect3D9_Release(d3d);
2453 static void test_scene(void)
2455 IDirect3DSurface9 *surface1, *surface2, *surface3;
2456 IDirect3DSurface9 *backBuffer, *rt, *ds;
2457 RECT rect = {0, 0, 128, 128};
2458 IDirect3DDevice9 *device;
2459 IDirect3D9 *d3d;
2460 ULONG refcount;
2461 D3DCAPS9 caps;
2462 HWND window;
2463 HRESULT hr;
2465 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2466 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2467 ok(!!window, "Failed to create a window.\n");
2468 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2469 ok(!!d3d, "Failed to create a D3D object.\n");
2470 if (!(device = create_device(d3d, window, NULL)))
2472 skip("Failed to create a 3D device, skipping test.\n");
2473 goto cleanup;
2476 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2477 memset(&caps, 0, sizeof(caps));
2478 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2479 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2481 /* Test an EndScene without BeginScene. Should return an error */
2482 hr = IDirect3DDevice9_EndScene(device);
2483 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2485 /* Test a normal BeginScene / EndScene pair, this should work */
2486 hr = IDirect3DDevice9_BeginScene(device);
2487 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2488 hr = IDirect3DDevice9_EndScene(device);
2489 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2491 /* Test another EndScene without having begun a new scene. Should return an error */
2492 hr = IDirect3DDevice9_EndScene(device);
2493 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2495 /* Two nested BeginScene and EndScene calls */
2496 hr = IDirect3DDevice9_BeginScene(device);
2497 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2498 hr = IDirect3DDevice9_BeginScene(device);
2499 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2500 hr = IDirect3DDevice9_EndScene(device);
2501 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2502 hr = IDirect3DDevice9_EndScene(device);
2503 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2505 /* Create some surfaces to test stretchrect between the scenes */
2506 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2507 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2508 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2509 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2510 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2511 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2512 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2513 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2514 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2515 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2516 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2517 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2519 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2520 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2521 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2522 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2524 /* First make sure a simple StretchRect call works */
2525 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2526 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2527 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2528 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2529 if (0) /* Disabled for now because it crashes in wine */
2531 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2532 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2533 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2536 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2537 * BeginScene - Endscene pair with normal surfaces and render targets, but
2538 * not depth stencil surfaces. */
2539 hr = IDirect3DDevice9_BeginScene(device);
2540 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2542 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2543 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2544 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2545 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2546 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2547 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2548 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2550 hr = IDirect3DDevice9_EndScene(device);
2551 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2553 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2554 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2555 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2557 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2558 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2559 hr = IDirect3DDevice9_BeginScene(device);
2560 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2561 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2562 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2563 hr = IDirect3DDevice9_EndScene(device);
2564 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2566 IDirect3DSurface9_Release(rt);
2567 IDirect3DSurface9_Release(ds);
2568 IDirect3DSurface9_Release(backBuffer);
2569 IDirect3DSurface9_Release(surface1);
2570 IDirect3DSurface9_Release(surface2);
2571 IDirect3DSurface9_Release(surface3);
2572 refcount = IDirect3DDevice9_Release(device);
2573 ok(!refcount, "Device has %u references left.\n", refcount);
2574 cleanup:
2575 IDirect3D9_Release(d3d);
2576 DestroyWindow(window);
2579 static void test_limits(void)
2581 IDirect3DTexture9 *texture;
2582 IDirect3DDevice9 *device;
2583 IDirect3D9 *d3d;
2584 unsigned int i;
2585 ULONG refcount;
2586 HWND window;
2587 HRESULT hr;
2589 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2590 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2591 ok(!!window, "Failed to create a window.\n");
2592 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2593 ok(!!d3d, "Failed to create a D3D object.\n");
2594 if (!(device = create_device(d3d, window, NULL)))
2596 skip("Failed to create a 3D device, skipping test.\n");
2597 goto cleanup;
2600 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2601 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2603 /* There are 16 pixel samplers. We should be able to access all of them */
2604 for (i = 0; i < 16; ++i)
2606 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2607 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2608 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2609 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2610 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2611 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2614 /* Now test all 8 textures stage states */
2615 for (i = 0; i < 8; ++i)
2617 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2618 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2621 /* Investigations show that accessing higher samplers / textures stage
2622 * states does not return an error either. Writing to too high samplers
2623 * (approximately sampler 40) causes memory corruption in Windows, so
2624 * there is no bounds checking. */
2625 IDirect3DTexture9_Release(texture);
2626 refcount = IDirect3D9_Release(device);
2627 ok(!refcount, "Device has %u references left.\n", refcount);
2628 cleanup:
2629 IDirect3D9_Release(d3d);
2630 DestroyWindow(window);
2633 static void test_depthstenciltest(void)
2635 HRESULT hr;
2636 IDirect3DDevice9 *pDevice = NULL;
2637 D3DPRESENT_PARAMETERS d3dpp;
2638 D3DDISPLAYMODE d3ddm;
2639 IDirect3DSurface9 *pDepthStencil = NULL;
2640 IDirect3DSurface9 *pDepthStencil2 = NULL;
2641 IDirect3D9 *d3d;
2642 DWORD state;
2643 HWND hwnd;
2645 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2646 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2647 ok(!!hwnd, "Failed to create a window.\n");
2648 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2649 ok(!!d3d, "Failed to create a D3D object.\n");
2651 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2652 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2653 d3dpp.Windowed = TRUE;
2654 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2655 d3dpp.BackBufferWidth = 800;
2656 d3dpp.BackBufferHeight = 600;
2657 d3dpp.BackBufferFormat = d3ddm.Format;
2658 d3dpp.EnableAutoDepthStencil = TRUE;
2659 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2661 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2662 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2663 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2664 if(!pDevice)
2666 skip("Failed to create a d3d device\n");
2667 goto cleanup;
2670 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2671 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2673 /* Try to clear */
2674 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2675 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2677 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2678 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2680 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2681 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2682 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2683 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2685 /* This left the render states untouched! */
2686 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2687 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2688 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2689 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2690 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2691 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2692 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2693 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2694 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2695 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2696 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2697 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2699 /* This is supposed to fail now */
2700 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2701 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2703 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2704 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2706 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2707 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2709 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2710 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2711 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2713 /* Now it works again */
2714 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2715 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2717 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2718 if(pDevice) IDirect3D9_Release(pDevice);
2720 /* Now see if autodepthstencil disable is honored. First, without a format set */
2721 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2722 d3dpp.Windowed = TRUE;
2723 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2724 d3dpp.BackBufferWidth = 800;
2725 d3dpp.BackBufferHeight = 600;
2726 d3dpp.BackBufferFormat = d3ddm.Format;
2727 d3dpp.EnableAutoDepthStencil = FALSE;
2728 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2730 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2731 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2732 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2733 if(!pDevice)
2735 skip("Failed to create a d3d device\n");
2736 goto cleanup;
2739 pDepthStencil = NULL;
2740 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2741 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2742 if(pDepthStencil) {
2743 IDirect3DSurface9_Release(pDepthStencil);
2744 pDepthStencil = NULL;
2747 /* Check the depth test state */
2748 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2749 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2750 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2752 if(pDevice) IDirect3D9_Release(pDevice);
2754 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2755 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2756 d3dpp.Windowed = TRUE;
2757 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2758 d3dpp.BackBufferWidth = 800;
2759 d3dpp.BackBufferHeight = 600;
2760 d3dpp.BackBufferFormat = d3ddm.Format;
2761 d3dpp.EnableAutoDepthStencil = FALSE;
2762 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2764 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2765 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2766 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2767 if(!pDevice)
2769 skip("Failed to create a d3d device\n");
2770 goto cleanup;
2773 pDepthStencil = NULL;
2774 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2775 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2776 if(pDepthStencil) {
2777 IDirect3DSurface9_Release(pDepthStencil);
2778 pDepthStencil = NULL;
2781 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2782 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2783 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2785 cleanup:
2786 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2787 if (pDevice)
2789 UINT refcount = IDirect3D9_Release(pDevice);
2790 ok(!refcount, "Device has %u references left.\n", refcount);
2792 IDirect3D9_Release(d3d);
2793 DestroyWindow(hwnd);
2796 static void test_get_rt(void)
2798 IDirect3DSurface9 *backbuffer, *rt;
2799 IDirect3DDevice9 *device;
2800 IDirect3D9 *d3d9;
2801 D3DCAPS9 caps;
2802 HWND window;
2803 HRESULT hr;
2804 ULONG ref;
2805 UINT i;
2807 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2808 0, 0, 128, 128, 0, 0, 0, 0);
2809 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2810 ok(!!d3d9, "Failed to create a D3D object.\n");
2811 device = create_device(d3d9, window, NULL);
2812 if (!device)
2814 skip("Failed to create a D3D device, skipping tests.\n");
2815 goto done;
2818 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2819 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2820 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2822 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2823 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2825 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2827 rt = backbuffer;
2828 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2829 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2830 ok(!rt, "Got rt %p.\n", rt);
2833 IDirect3DSurface9_Release(backbuffer);
2835 ref = IDirect3DDevice9_Release(device);
2836 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2837 done:
2838 IDirect3D9_Release(d3d9);
2839 DestroyWindow(window);
2842 static void test_draw_primitive(void)
2844 static const struct
2846 float position[3];
2847 DWORD color;
2849 quad[] =
2851 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2852 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2853 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2854 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2856 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
2857 static const D3DVERTEXELEMENT9 decl_elements[] =
2859 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2860 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2861 D3DDECL_END()
2864 IDirect3DVertexDeclaration9 *vertex_declaration;
2865 IDirect3DVertexBuffer9 *vertex_buffer;
2866 IDirect3DIndexBuffer9 *index_buffer;
2867 IDirect3DDevice9 *device;
2868 IDirect3D9 *d3d9;
2869 ULONG refcount;
2870 HWND window;
2871 HRESULT hr;
2872 void *ptr;
2874 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
2875 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2876 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2877 ok(!!d3d9, "Failed to create a D3D object.\n");
2878 if (!(device = create_device(d3d9, window, NULL)))
2880 skip("Failed to create a D3D device.\n");
2881 IDirect3D9_Release(d3d9);
2882 DestroyWindow(window);
2883 return;
2886 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2887 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
2889 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
2890 D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2891 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#x.\n", hr);
2892 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2893 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2894 memcpy(ptr, quad, sizeof(quad));
2895 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2896 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2897 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2898 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#x.\n", hr);
2900 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
2901 D3DPOOL_DEFAULT, &index_buffer, NULL);
2902 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#x.\n", hr);
2903 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2904 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2905 memcpy(ptr, indices, sizeof(indices));
2906 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2907 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2909 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2910 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#x.\n", hr);
2912 hr = IDirect3DDevice9_BeginScene(device);
2913 ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2915 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2916 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2918 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2919 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2921 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2922 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2924 hr = IDirect3DDevice9_SetIndices(device, NULL);
2925 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2926 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2927 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2928 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2930 /* Valid index buffer, NULL vertex declaration. Should fail */
2931 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2932 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2933 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2934 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2935 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2937 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2938 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2939 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2941 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2942 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2944 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2945 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2947 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2948 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2950 /* NULL index buffer, valid vertex vertex declaration. Should succeed */
2951 hr = IDirect3DDevice9_SetIndices(device, NULL);
2952 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2953 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2954 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2955 todo_wine ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2957 /* Valid index buffer and vertex declaration. Should succeed */
2958 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2959 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2960 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2961 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2962 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2964 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2965 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2966 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#x.\n", hr);
2968 hr = IDirect3DDevice9_EndScene(device);
2969 ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2971 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2972 ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2974 IDirect3DVertexBuffer9_Release(vertex_buffer);
2975 IDirect3DIndexBuffer9_Release(index_buffer);
2976 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2977 refcount = IDirect3DDevice9_Release(device);
2978 ok(!refcount, "Device has %u references left.\n", refcount);
2979 IDirect3D9_Release(d3d9);
2980 DestroyWindow(window);
2983 static void test_null_stream(void)
2985 IDirect3DVertexBuffer9 *buffer = NULL;
2986 IDirect3DDevice9 *device;
2987 IDirect3D9 *d3d9;
2988 ULONG refcount;
2989 HWND window;
2990 HRESULT hr;
2991 IDirect3DVertexShader9 *shader = NULL;
2992 IDirect3DVertexDeclaration9 *decl = NULL;
2993 static const DWORD shader_code[] =
2995 0xfffe0101, /* vs_1_1 */
2996 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2997 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2998 0x0000ffff /* end */
3000 static const D3DVERTEXELEMENT9 decl_elements[] = {
3001 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3002 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3003 D3DDECL_END()
3006 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3007 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3008 ok(!!window, "Failed to create a window.\n");
3009 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3010 ok(!!d3d9, "Failed to create a D3D object.\n");
3011 if (!(device = create_device(d3d9, window, NULL)))
3013 skip("Failed to create a 3D device, skipping test.\n");
3014 goto cleanup;
3017 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
3018 if(FAILED(hr)) {
3019 skip("No vertex shader support\n");
3020 goto cleanup;
3022 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3023 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
3024 if (FAILED(hr)) {
3025 skip("Vertex declaration handling not possible.\n");
3026 goto cleanup;
3028 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
3029 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
3030 if (FAILED(hr)) {
3031 skip("Vertex buffer handling not possible.\n");
3032 goto cleanup;
3035 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
3036 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3037 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
3038 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3039 hr = IDirect3DDevice9_SetVertexShader(device, shader);
3040 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
3041 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3042 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
3044 hr = IDirect3DDevice9_BeginScene(device);
3045 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3046 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
3047 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3048 hr = IDirect3DDevice9_EndScene(device);
3049 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3051 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3052 IDirect3DDevice9_SetVertexShader(device, NULL);
3053 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3055 cleanup:
3056 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
3057 if (decl) IDirect3DVertexDeclaration9_Release(decl);
3058 if (shader) IDirect3DVertexShader9_Release(shader);
3059 if (device)
3061 refcount = IDirect3DDevice9_Release(device);
3062 ok(!refcount, "Device has %u references left.\n", refcount);
3064 IDirect3D9_Release(d3d9);
3065 DestroyWindow(window);
3068 static void test_lights(void)
3070 IDirect3DDevice9 *device;
3071 IDirect3D9 *d3d9;
3072 ULONG refcount;
3073 HWND window;
3074 HRESULT hr;
3075 unsigned int i;
3076 BOOL enabled;
3077 D3DCAPS9 caps;
3079 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3080 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3081 ok(!!window, "Failed to create a window.\n");
3082 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3083 ok(!!d3d9, "Failed to create a D3D object.\n");
3084 if (!(device = create_device(d3d9, window, NULL)))
3086 skip("Failed to create a 3D device, skipping test.\n");
3087 goto cleanup;
3090 memset(&caps, 0, sizeof(caps));
3091 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3092 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
3094 for(i = 1; i <= caps.MaxActiveLights; i++) {
3095 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
3096 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
3097 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
3098 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
3099 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
3102 /* TODO: Test the rendering results in this situation */
3103 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
3104 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
3105 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
3106 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
3107 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
3108 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
3109 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
3111 for(i = 1; i <= caps.MaxActiveLights; i++) {
3112 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
3113 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
3116 refcount = IDirect3DDevice9_Release(device);
3117 ok(!refcount, "Device has %u references left.\n", refcount);
3118 cleanup:
3119 IDirect3D9_Release(d3d9);
3120 DestroyWindow(window);
3123 static void test_set_stream_source(void)
3125 IDirect3DVertexBuffer9 *vb;
3126 IDirect3DDevice9 *device;
3127 IDirect3D9 *d3d9;
3128 ULONG refcount;
3129 HWND window;
3130 HRESULT hr;
3132 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3133 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3134 ok(!!window, "Failed to create a window.\n");
3135 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3136 ok(!!d3d9, "Failed to create a D3D object.\n");
3137 if (!(device = create_device(d3d9, window, NULL)))
3139 skip("Failed to create a 3D device, skipping test.\n");
3140 goto cleanup;
3143 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
3144 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
3146 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
3147 * (Radeon 9000 verified) reject them, so accept both results. Wine
3148 * currently rejects this to be able to optimize the vbo conversion, but
3149 * writes a WARN. */
3150 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
3151 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3152 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
3153 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3154 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
3155 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3156 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
3157 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3158 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
3159 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3161 /* Try to set the NULL buffer with an offset and stride 0 */
3162 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3163 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3164 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
3165 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3166 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
3167 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3168 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
3169 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3170 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
3171 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3173 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3174 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3176 IDirect3DVertexBuffer9_Release(vb);
3177 refcount = IDirect3DDevice9_Release(device);
3178 ok(!refcount, "Device has %u references left.\n", refcount);
3179 cleanup:
3180 IDirect3D9_Release(d3d9);
3181 DestroyWindow(window);
3184 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
3185 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
3186 * a fixed number of combinations are possible in fullscreen mode. In windowed
3187 * mode more combinations are allowed due to format conversion and this is
3188 * likely driver dependent. */
3189 static void test_display_formats(void)
3191 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
3192 unsigned int backbuffer, display;
3193 unsigned int windowed;
3194 IDirect3D9 *d3d9;
3195 BOOL should_pass;
3196 BOOL has_modes;
3197 HRESULT hr;
3199 static const struct
3201 const char *name;
3202 D3DFORMAT format;
3203 D3DFORMAT alpha_format;
3204 BOOL display;
3205 BOOL windowed;
3207 formats[] =
3209 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
3210 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
3211 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
3212 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
3213 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3214 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3215 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3218 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3219 ok(!!d3d9, "Failed to create a D3D object.\n");
3221 for (display = 0; display < ARRAY_SIZE(formats); ++display)
3223 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3225 for (windowed = 0; windowed <= 1; ++windowed)
3227 for (backbuffer = 0; backbuffer < ARRAY_SIZE(formats); ++backbuffer)
3229 should_pass = FALSE;
3231 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3233 D3DFORMAT backbuffer_format;
3235 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3236 backbuffer_format = formats[display].format;
3237 else
3238 backbuffer_format = formats[backbuffer].format;
3240 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3241 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3242 if (hr == D3D_OK)
3244 if (windowed)
3246 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3247 backbuffer_format, formats[display].format);
3248 should_pass = (hr == D3D_OK);
3250 else
3251 should_pass = (formats[display].format == formats[backbuffer].format
3252 || (formats[display].alpha_format
3253 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3257 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3258 formats[display].format, formats[backbuffer].format, windowed);
3259 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3260 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3261 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3266 IDirect3D9_Release(d3d9);
3269 static void test_scissor_size(void)
3271 struct device_desc device_desc;
3272 IDirect3D9 *d3d9_ptr;
3273 unsigned int i;
3274 static struct {
3275 int winx; int winy; int backx; int backy; DWORD flags;
3276 } scts[] = { /* scissor tests */
3277 {800, 600, 640, 480, 0},
3278 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3279 {640, 480, 800, 600, 0},
3280 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3283 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3284 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3286 for (i = 0; i < ARRAY_SIZE(scts); i++)
3288 IDirect3DDevice9 *device_ptr = 0;
3289 HRESULT hr;
3290 HWND hwnd = 0;
3291 RECT scissorrect;
3293 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3294 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3296 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3298 scts[i].backx = registry_mode.dmPelsWidth;
3299 scts[i].backy = registry_mode.dmPelsHeight;
3302 device_desc.device_window = hwnd;
3303 device_desc.width = scts[i].backx;
3304 device_desc.height = scts[i].backy;
3305 device_desc.flags = scts[i].flags;
3306 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3308 skip("Failed to create a 3D device, skipping test.\n");
3309 DestroyWindow(hwnd);
3310 goto err_out;
3313 /* Check for the default scissor rect size */
3314 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3315 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3316 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3317 && scissorrect.top == 0 && scissorrect.left == 0,
3318 "Scissorrect mismatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3319 scts[i].backx, scts[i].backy);
3321 /* check the scissorrect values after a reset */
3322 device_desc.width = registry_mode.dmPelsWidth;
3323 device_desc.height = registry_mode.dmPelsHeight;
3324 device_desc.flags = scts[i].flags;
3325 hr = reset_device(device_ptr, &device_desc);
3326 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3327 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3328 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3330 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3331 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3332 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3333 && scissorrect.top == 0 && scissorrect.left == 0,
3334 "Scissorrect mismatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3335 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3337 if (device_ptr)
3339 ULONG ref;
3341 ref = IDirect3DDevice9_Release(device_ptr);
3342 DestroyWindow(hwnd);
3343 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3347 err_out:
3348 IDirect3D9_Release(d3d9_ptr);
3351 static void test_multi_device(void)
3353 IDirect3DDevice9 *device1, *device2;
3354 HWND window1, window2;
3355 IDirect3D9 *d3d9;
3356 ULONG refcount;
3358 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3359 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3360 ok(!!window1, "Failed to create a window.\n");
3361 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3362 ok(!!d3d9, "Failed to create a D3D object.\n");
3363 if (!(device1 = create_device(d3d9, window1, NULL)))
3365 skip("Failed to create a 3D device, skipping test.\n");
3366 IDirect3D9_Release(d3d9);
3367 DestroyWindow(window1);
3368 return;
3370 IDirect3D9_Release(d3d9);
3372 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3373 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3374 ok(!!window2, "Failed to create a window.\n");
3375 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3376 ok(!!d3d9, "Failed to create a D3D object.\n");
3377 device2 = create_device(d3d9, window2, NULL);
3378 IDirect3D9_Release(d3d9);
3380 refcount = IDirect3DDevice9_Release(device2);
3381 ok(!refcount, "Device has %u references left.\n", refcount);
3382 refcount = IDirect3DDevice9_Release(device1);
3383 ok(!refcount, "Device has %u references left.\n", refcount);
3384 DestroyWindow(window2);
3385 DestroyWindow(window1);
3388 static HWND filter_messages;
3390 enum message_window
3392 DEVICE_WINDOW,
3393 FOCUS_WINDOW,
3396 struct message
3398 UINT message;
3399 enum message_window window;
3400 BOOL check_wparam;
3401 WPARAM expect_wparam;
3402 WINDOWPOS *store_wp;
3405 static const struct message *expect_messages;
3406 static HWND device_window, focus_window;
3407 static LONG windowposchanged_received, syscommand_received, wm_size_received;
3409 struct wndproc_thread_param
3411 HWND dummy_window;
3412 HANDLE window_created;
3413 HANDLE test_finished;
3414 BOOL running_in_foreground;
3417 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3419 if (filter_messages && filter_messages == hwnd)
3421 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3422 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3425 if (expect_messages)
3427 HWND w;
3429 switch (expect_messages->window)
3431 case DEVICE_WINDOW:
3432 w = device_window;
3433 break;
3435 case FOCUS_WINDOW:
3436 w = focus_window;
3437 break;
3439 default:
3440 w = NULL;
3441 break;
3444 if (hwnd == w && expect_messages->message == message)
3446 if (expect_messages->check_wparam)
3447 ok(wparam == expect_messages->expect_wparam,
3448 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3449 wparam, message, expect_messages->expect_wparam);
3451 if (expect_messages->store_wp)
3452 *expect_messages->store_wp = *(WINDOWPOS *)lparam;
3454 ++expect_messages;
3458 /* KDE randomly does something with the hidden window during the
3459 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3460 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3461 * just flag WM_WINDOWPOSCHANGED as bad. */
3462 if (message == WM_WINDOWPOSCHANGED)
3463 InterlockedIncrement(&windowposchanged_received);
3464 else if (message == WM_SYSCOMMAND)
3465 InterlockedIncrement(&syscommand_received);
3466 else if (message == WM_SIZE)
3467 InterlockedIncrement(&wm_size_received);
3469 return DefWindowProcA(hwnd, message, wparam, lparam);
3472 static DWORD WINAPI wndproc_thread(void *param)
3474 struct wndproc_thread_param *p = param;
3475 DWORD res;
3476 BOOL ret;
3478 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3479 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3480 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3481 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3483 ret = SetEvent(p->window_created);
3484 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3486 for (;;)
3488 MSG msg;
3490 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3491 res = WaitForSingleObject(p->test_finished, 100);
3492 if (res == WAIT_OBJECT_0) break;
3493 if (res != WAIT_TIMEOUT)
3495 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3496 break;
3500 DestroyWindow(p->dummy_window);
3502 return 0;
3505 static void test_wndproc(void)
3507 struct wndproc_thread_param thread_params;
3508 struct device_desc device_desc;
3509 IDirect3DDevice9 *device;
3510 WNDCLASSA wc = {0};
3511 IDirect3D9 *d3d9;
3512 HANDLE thread;
3513 LONG_PTR proc;
3514 ULONG ref;
3515 DWORD res, tid;
3516 HWND tmp;
3517 UINT i, adapter_mode_count;
3518 HRESULT hr;
3519 D3DDISPLAYMODE d3ddm;
3520 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3521 DEVMODEW devmode;
3522 LONG change_ret, device_style;
3523 BOOL ret;
3524 WINDOWPOS windowpos;
3526 static const struct message create_messages[] =
3528 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3529 /* Do not test wparam here. If device creation succeeds,
3530 * wparam is WA_ACTIVE. If device creation fails (testbot)
3531 * wparam is set to WA_INACTIVE on some Windows versions. */
3532 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3533 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3534 {0, 0, FALSE, 0},
3536 static const struct message focus_loss_messages[] =
3538 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3539 * not reliable on X11 WMs. When the window focus follows the
3540 * mouse pointer the message is not sent.
3541 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3542 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3543 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3544 * not deterministic. */
3545 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3546 /* Windows sends WM_ACTIVATE to the device window, indicating that
3547 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3548 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3549 * leaves the device window active, breaking re-activation in the
3550 * lost device test.
3551 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3552 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3553 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3554 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3555 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3556 * not deterministic. It may be sent after the focus window handling
3557 * or before. */
3558 {0, 0, FALSE, 0},
3560 static const struct message focus_loss_messages_nowc[] =
3562 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3563 * not reliable on X11 WMs. When the window focus follows the
3564 * mouse pointer the message is not sent.
3565 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3566 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3567 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3568 {0, 0, FALSE, 0},
3570 static const struct message reactivate_messages[] =
3572 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3573 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3574 /* optional WM_MOVE here if size changed */
3575 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3576 {0, 0, FALSE, 0},
3578 static const struct message reactivate_messages_nowc[] =
3580 /* We're activating the device window before activating the
3581 * focus window, so no ACTIVATEAPP message is sent. */
3582 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3583 {0, 0, FALSE, 0},
3585 static const struct message focus_loss_messages_hidden[] =
3587 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3588 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3589 {0, 0, FALSE, 0},
3591 static const struct message focus_loss_messages_filtered[] =
3593 /* WM_ACTIVATE is delivered to the window proc because it is
3594 * generated by SetForegroundWindow before the d3d routine
3595 * starts it work. Don't check for it due to focus-follows-mouse
3596 * WMs though. */
3597 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3598 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3599 {0, 0, FALSE, 0},
3601 static const struct message reactivate_messages_filtered[] =
3603 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3604 {0, 0, FALSE, 0},
3606 static const struct message sc_restore_messages[] =
3608 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3609 * processed it. Our wndproc has no way to prevent d3d from
3610 * handling the message. The second DefWindowProc call done by
3611 * our wndproc doesn't do any changes to the window because it
3612 * is already restored due to d3d's handling. */
3613 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3614 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3615 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3616 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3617 {0, 0, FALSE, 0},
3619 static const struct message sc_minimize_messages[] =
3621 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3622 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3623 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3624 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3625 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3626 {0, 0, FALSE, 0},
3628 static const struct message sc_maximize_messages[] =
3630 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3631 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3632 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3633 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3634 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3635 {0, 0, FALSE, 0},
3637 struct message mode_change_messages[] =
3639 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3640 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3641 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3642 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3643 * differs between Wine and Windows. */
3644 /* TODO 2: Windows sends a second WM_WINDOWPOSCHANGING(SWP_NOMOVE | SWP_NOSIZE
3645 * | SWP_NOACTIVATE) in this situation, suggesting a difference in their ShowWindow
3646 * implementation. This SetWindowPos call could in theory affect the Z order. Wine's
3647 * ShowWindow does not send such a message because the window is already visible. */
3648 {0, 0, FALSE, 0},
3650 struct message mode_change_messages_hidden[] =
3652 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3653 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3654 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3655 {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0},
3656 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, &windowpos},
3657 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3658 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3659 * differs between Wine and Windows. */
3660 {0, 0, FALSE, 0},
3662 static const struct message mode_change_messages_nowc[] =
3664 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3665 {0, 0, FALSE, 0},
3667 struct
3669 DWORD create_flags;
3670 const struct message *focus_loss_messages, *reactivate_messages;
3671 const struct message *mode_change_messages, *mode_change_messages_hidden;
3672 BOOL iconic;
3674 tests[] =
3678 focus_loss_messages,
3679 reactivate_messages,
3680 mode_change_messages,
3681 mode_change_messages_hidden,
3682 TRUE
3685 CREATE_DEVICE_NOWINDOWCHANGES,
3686 focus_loss_messages_nowc,
3687 reactivate_messages_nowc,
3688 mode_change_messages_nowc,
3689 mode_change_messages_nowc,
3690 FALSE
3694 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3695 ok(!!d3d9, "Failed to create a D3D object.\n");
3697 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3698 for (i = 0; i < adapter_mode_count; ++i)
3700 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3701 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3703 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3704 continue;
3705 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3706 * refuses to create a device at these sizes. */
3707 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3708 continue;
3710 if (!user32_width)
3712 user32_width = d3ddm.Width;
3713 user32_height = d3ddm.Height;
3714 continue;
3717 /* Make sure the d3d mode is smaller in width or height and at most
3718 * equal in the other dimension than the mode passed to
3719 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3720 * the ChangeDisplaySettings parameters + 12. */
3721 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3722 continue;
3723 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3725 d3d_width = d3ddm.Width;
3726 d3d_height = d3ddm.Height;
3727 break;
3729 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3731 d3d_width = user32_width;
3732 d3d_height = user32_height;
3733 user32_width = d3ddm.Width;
3734 user32_height = d3ddm.Height;
3735 break;
3739 if (!d3d_width)
3741 skip("Could not find adequate modes, skipping mode tests.\n");
3742 IDirect3D9_Release(d3d9);
3743 return;
3746 wc.lpfnWndProc = test_proc;
3747 wc.lpszClassName = "d3d9_test_wndproc_wc";
3748 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3750 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3751 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3752 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3753 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3755 memset(&devmode, 0, sizeof(devmode));
3756 devmode.dmSize = sizeof(devmode);
3757 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3759 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3760 devmode.dmPelsWidth = user32_width;
3761 devmode.dmPelsHeight = user32_height;
3762 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3763 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3765 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3766 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3767 device_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 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3770 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3772 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3773 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3775 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3776 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3777 (LONG_PTR)test_proc, proc);
3778 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3779 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3780 (LONG_PTR)test_proc, proc);
3782 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3783 device_window, focus_window, thread_params.dummy_window);
3785 tmp = GetFocus();
3786 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3787 if (thread_params.running_in_foreground)
3789 tmp = GetForegroundWindow();
3790 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3791 thread_params.dummy_window, tmp);
3793 else
3794 skip("Not running in foreground, skip foreground window test\n");
3796 flush_events();
3798 expect_messages = create_messages;
3800 device_desc.device_window = device_window;
3801 device_desc.width = d3d_width;
3802 device_desc.height = d3d_height;
3803 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3804 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3806 skip("Failed to create a D3D device, skipping tests.\n");
3807 goto done;
3810 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3811 expect_messages->message, expect_messages->window, i);
3812 expect_messages = NULL;
3814 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3816 tmp = GetFocus();
3817 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3818 tmp = GetForegroundWindow();
3819 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3821 SetForegroundWindow(focus_window);
3822 flush_events();
3824 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3825 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3826 (LONG_PTR)test_proc, proc, i);
3828 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3829 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3830 (LONG_PTR)test_proc, i);
3832 /* Change the mode while the device is in use and then drop focus. */
3833 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3834 devmode.dmPelsWidth = user32_width;
3835 devmode.dmPelsHeight = user32_height;
3836 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3837 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3839 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3840 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3841 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3842 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3843 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3844 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3846 expect_messages = tests[i].focus_loss_messages;
3847 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3848 * manually changing the focus. It generates the same messages, but the task
3849 * bar still shows the previous foreground window as active, and the window has
3850 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3851 * the device is difficult, see below. */
3852 SetForegroundWindow(GetDesktopWindow());
3853 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3854 expect_messages->message, expect_messages->window, i);
3855 expect_messages = NULL;
3856 tmp = GetFocus();
3857 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3858 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3860 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3861 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3863 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3864 ok(ret, "Failed to get display mode.\n");
3865 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3866 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3867 devmode.dmPelsWidth, devmode.dmPelsHeight);
3869 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3870 * done before the focus window is restored. This makes sense to some extent
3871 * because minimizing the window on focus loss is the application's job if this
3872 * flag is set. */
3873 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3875 ShowWindow(device_window, SW_MINIMIZE);
3876 ShowWindow(device_window, SW_RESTORE);
3878 flush_events();
3880 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3881 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3882 * restore is triggered by the user. */
3883 expect_messages = tests[i].reactivate_messages;
3884 ShowWindow(focus_window, SW_MINIMIZE);
3885 ShowWindow(focus_window, SW_RESTORE);
3886 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3887 SetForegroundWindow(focus_window);
3888 flush_events();
3889 SetForegroundWindow(focus_window);
3890 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3891 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3892 expect_messages->message, expect_messages->window, i);
3893 expect_messages = NULL;
3895 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3896 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3898 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3899 ok(ret, "Failed to get display mode.\n");
3900 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3901 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3902 devmode.dmPelsWidth, devmode.dmPelsHeight);
3904 hr = reset_device(device, &device_desc);
3905 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3907 /* Remove the WS_VISIBLE flag to test hidden windows. This is enough to trigger d3d's hidden
3908 * window codepath, but does not actually hide the window without a SetWindowPos(SWP_FRAMECHANGED)
3909 * call. This way we avoid focus changes and random failures on focus follows mouse WMs. */
3910 device_style = GetWindowLongA(device_window, GWL_STYLE);
3911 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3912 flush_events();
3914 expect_messages = focus_loss_messages_hidden;
3915 windowposchanged_received = 0;
3916 SetForegroundWindow(GetDesktopWindow());
3917 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3918 expect_messages->message, expect_messages->window, i);
3919 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3920 expect_messages = NULL;
3921 flush_events();
3923 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3924 ok(ret, "Failed to get display mode.\n");
3925 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3926 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3928 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3929 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3930 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3931 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3932 flush_events();
3934 syscommand_received = 0;
3935 expect_messages = sc_restore_messages;
3936 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3937 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3938 expect_messages->message, expect_messages->window, i);
3939 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3940 expect_messages = NULL;
3941 flush_events();
3943 expect_messages = sc_minimize_messages;
3944 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3945 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3946 expect_messages->message, expect_messages->window, i);
3947 expect_messages = NULL;
3948 flush_events();
3950 expect_messages = sc_maximize_messages;
3951 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3952 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3953 expect_messages->message, expect_messages->window, i);
3954 expect_messages = NULL;
3955 flush_events();
3957 SetForegroundWindow(GetDesktopWindow());
3958 ShowWindow(device_window, SW_MINIMIZE);
3959 ShowWindow(device_window, SW_RESTORE);
3960 ShowWindow(focus_window, SW_MINIMIZE);
3961 ShowWindow(focus_window, SW_RESTORE);
3962 SetForegroundWindow(focus_window);
3963 flush_events();
3965 /* Releasing a device in lost state breaks follow-up tests on native. */
3966 hr = reset_device(device, &device_desc);
3967 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3969 filter_messages = focus_window;
3971 ref = IDirect3DDevice9_Release(device);
3972 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3974 /* Fix up the mode until Wine's device release behavior is fixed. */
3975 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3976 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3978 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3979 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3980 (LONG_PTR)test_proc, proc, i);
3982 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3983 * on native in the test below. It isn't needed anyways. Creating the third
3984 * device will show it again. */
3985 filter_messages = NULL;
3986 ShowWindow(device_window, SW_HIDE);
3987 /* Remove the maximized state from the SYSCOMMAND test while we're not
3988 * interfering with a device. */
3989 ShowWindow(focus_window, SW_SHOWNORMAL);
3990 filter_messages = focus_window;
3992 device_desc.device_window = focus_window;
3993 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3995 skip("Failed to create a D3D device, skipping tests.\n");
3996 goto done;
3998 filter_messages = NULL;
3999 SetForegroundWindow(focus_window); /* For KDE. */
4000 flush_events();
4002 expect_messages = focus_loss_messages_filtered;
4003 windowposchanged_received = 0;
4004 SetForegroundWindow(GetDesktopWindow());
4005 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4006 expect_messages->message, expect_messages->window, i);
4007 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4008 expect_messages = NULL;
4010 /* The window is iconic even though no message was sent. */
4011 ok(!IsIconic(focus_window) == !tests[i].iconic,
4012 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
4014 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4015 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
4017 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4018 ShowWindow(focus_window, SW_MINIMIZE);
4020 syscommand_received = 0;
4021 expect_messages = sc_restore_messages;
4022 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
4023 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4024 expect_messages->message, expect_messages->window, i);
4025 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
4026 expect_messages = NULL;
4027 flush_events();
4029 /* For FVWM. */
4030 ShowWindow(focus_window, SW_RESTORE);
4031 flush_events();
4033 expect_messages = sc_minimize_messages;
4034 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
4035 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4036 expect_messages->message, expect_messages->window, i);
4037 expect_messages = NULL;
4038 flush_events();
4040 expect_messages = sc_maximize_messages;
4041 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
4042 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4043 expect_messages->message, expect_messages->window, i);
4044 expect_messages = NULL;
4045 flush_events();
4047 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
4048 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
4049 SetForegroundWindow(GetDesktopWindow());
4050 flush_events();
4051 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
4052 flush_events();
4054 expect_messages = reactivate_messages_filtered;
4055 windowposchanged_received = 0;
4056 SetForegroundWindow(focus_window);
4057 flush_events();
4058 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4059 expect_messages->message, expect_messages->window, i);
4060 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
4061 ok(!windowposchanged_received || broken(1),
4062 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4063 expect_messages = NULL;
4065 filter_messages = focus_window;
4066 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4067 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
4069 hr = reset_device(device, &device_desc);
4070 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4072 ref = IDirect3DDevice9_Release(device);
4073 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4075 device_desc.device_window = device_window;
4076 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4078 skip("Failed to create a D3D device, skipping tests.\n");
4079 goto done;
4081 filter_messages = NULL;
4082 flush_events();
4084 device_desc.width = user32_width;
4085 device_desc.height = user32_height;
4087 expect_messages = tests[i].mode_change_messages;
4088 filter_messages = focus_window;
4089 hr = reset_device(device, &device_desc);
4090 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4091 filter_messages = NULL;
4093 /* The WINDOWPOS structure passed to the first WM_WINDOWPOSCHANGING differs between windows versions.
4094 * Prior to Win10 17.03 it is consistent with a MoveWindow(0, 0, width, height) call. Since Windows
4095 * 10 17.03 it has x = 0, y = 0, width = 0, height = 0, flags = SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE
4096 * | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER (0x1837). Visually
4097 * it is clear that the window has not been resized. In previous Windows version the window is resized. */
4099 flush_events();
4100 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4101 expect_messages->message, expect_messages->window, i);
4103 /* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
4104 device_style = GetWindowLongA(device_window, GWL_STYLE);
4105 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
4107 flush_events();
4108 device_desc.width = d3d_width;
4109 device_desc.height = d3d_height;
4110 memset(&windowpos, 0, sizeof(windowpos));
4112 expect_messages = tests[i].mode_change_messages_hidden;
4113 filter_messages = focus_window;
4114 hr = reset_device(device, &device_desc);
4115 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4116 filter_messages = NULL;
4118 flush_events();
4119 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4120 expect_messages->message, expect_messages->window, i);
4122 if (!(tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES))
4124 ok(windowpos.hwnd == device_window && !windowpos.hwndInsertAfter
4125 && !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
4126 && windowpos.flags == (SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE),
4127 "Got unexpected WINDOWPOS hwnd=%p, insertAfter=%p, x=%d, y=%d, cx=%d, cy=%d, flags=%x\n",
4128 windowpos.hwnd, windowpos.hwndInsertAfter, windowpos.x, windowpos.y, windowpos.cx,
4129 windowpos.cy, windowpos.flags);
4132 device_style = GetWindowLongA(device_window, GWL_STYLE);
4133 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4135 todo_wine ok(!(device_style & WS_VISIBLE), "Expected the device window to be hidden, i=%u.\n", i);
4136 ShowWindow(device_window, SW_MINIMIZE);
4137 ShowWindow(device_window, SW_RESTORE);
4139 else
4141 ok(device_style & WS_VISIBLE, "Expected the device window to be visible, i=%u.\n", i);
4144 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
4145 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
4146 (LONG_PTR)test_proc, i);
4148 filter_messages = focus_window;
4149 ref = IDirect3DDevice9_Release(device);
4150 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4152 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4153 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4154 (LONG_PTR)DefWindowProcA, proc, i);
4156 done:
4157 filter_messages = NULL;
4158 DestroyWindow(device_window);
4159 DestroyWindow(focus_window);
4160 SetEvent(thread_params.test_finished);
4161 WaitForSingleObject(thread, INFINITE);
4162 CloseHandle(thread);
4165 IDirect3D9_Release(d3d9);
4166 CloseHandle(thread_params.test_finished);
4167 CloseHandle(thread_params.window_created);
4168 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4171 static void test_wndproc_windowed(void)
4173 struct wndproc_thread_param thread_params;
4174 struct device_desc device_desc;
4175 IDirect3DDevice9 *device;
4176 WNDCLASSA wc = {0};
4177 IDirect3D9 *d3d9;
4178 HANDLE thread;
4179 LONG_PTR proc;
4180 HRESULT hr;
4181 ULONG ref;
4182 DWORD res, tid;
4183 HWND tmp;
4185 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4186 ok(!!d3d9, "Failed to create a D3D object.\n");
4188 wc.lpfnWndProc = test_proc;
4189 wc.lpszClassName = "d3d9_test_wndproc_wc";
4190 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4192 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4193 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4194 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4195 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4197 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4198 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4199 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4200 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4201 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4202 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4203 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4204 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4206 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4207 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4209 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4210 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4211 (LONG_PTR)test_proc, proc);
4212 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4213 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4214 (LONG_PTR)test_proc, proc);
4216 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4217 device_window, focus_window, thread_params.dummy_window);
4219 tmp = GetFocus();
4220 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4221 if (thread_params.running_in_foreground)
4223 tmp = GetForegroundWindow();
4224 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4225 thread_params.dummy_window, tmp);
4227 else
4228 skip("Not running in foreground, skip foreground window test\n");
4230 filter_messages = focus_window;
4232 device_desc.device_window = device_window;
4233 device_desc.width = 640;
4234 device_desc.height = 480;
4235 device_desc.flags = 0;
4236 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4238 skip("Failed to create a D3D device, skipping tests.\n");
4239 goto done;
4242 tmp = GetFocus();
4243 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4244 tmp = GetForegroundWindow();
4245 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4246 thread_params.dummy_window, tmp);
4248 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4249 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4250 (LONG_PTR)test_proc, proc);
4252 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4253 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4254 (LONG_PTR)test_proc, proc);
4256 filter_messages = NULL;
4258 device_desc.width = registry_mode.dmPelsWidth;
4259 device_desc.height = registry_mode.dmPelsHeight;
4260 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4261 hr = reset_device(device, &device_desc);
4262 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4264 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4265 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4266 (LONG_PTR)test_proc, proc);
4268 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4269 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4271 device_desc.flags = 0;
4272 hr = reset_device(device, &device_desc);
4273 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4275 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4276 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4277 (LONG_PTR)test_proc, proc);
4279 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4280 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4281 (LONG_PTR)test_proc, proc);
4283 filter_messages = focus_window;
4285 ref = IDirect3DDevice9_Release(device);
4286 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4288 filter_messages = device_window;
4290 device_desc.device_window = focus_window;
4291 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4293 skip("Failed to create a D3D device, skipping tests.\n");
4294 goto done;
4297 filter_messages = NULL;
4299 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4300 hr = reset_device(device, &device_desc);
4301 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4303 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4304 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4305 (LONG_PTR)test_proc, proc);
4307 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4308 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4310 device_desc.flags = 0;
4311 hr = reset_device(device, &device_desc);
4312 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4314 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4315 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4316 (LONG_PTR)test_proc, proc);
4318 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4319 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4320 (LONG_PTR)test_proc, proc);
4322 filter_messages = device_window;
4324 ref = IDirect3DDevice9_Release(device);
4325 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4327 device_desc.device_window = device_window;
4328 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4330 skip("Failed to create a D3D device, skipping tests.\n");
4331 goto done;
4334 filter_messages = NULL;
4336 device_desc.device_window = device_window;
4337 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4338 hr = reset_device(device, &device_desc);
4339 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4341 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4342 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4343 (LONG_PTR)test_proc, proc);
4345 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4346 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4348 device_desc.flags = 0;
4349 hr = reset_device(device, &device_desc);
4350 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4352 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4353 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4354 (LONG_PTR)test_proc, proc);
4356 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4357 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4358 (LONG_PTR)test_proc, proc);
4360 filter_messages = device_window;
4362 ref = IDirect3DDevice9_Release(device);
4363 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4365 done:
4366 filter_messages = NULL;
4367 IDirect3D9_Release(d3d9);
4369 SetEvent(thread_params.test_finished);
4370 WaitForSingleObject(thread, INFINITE);
4371 CloseHandle(thread_params.test_finished);
4372 CloseHandle(thread_params.window_created);
4373 CloseHandle(thread);
4375 DestroyWindow(device_window);
4376 DestroyWindow(focus_window);
4377 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4380 static void test_reset_fullscreen(void)
4382 struct device_desc device_desc;
4383 D3DDISPLAYMODE d3ddm, d3ddm2;
4384 unsigned int mode_count, i;
4385 IDirect3DDevice9 *device;
4386 WNDCLASSEXA wc = {0};
4387 IDirect3D9 *d3d;
4388 HRESULT hr;
4389 ATOM atom;
4390 static const struct message messages[] =
4392 /* Windows usually sends wparam = TRUE, except on the testbot,
4393 * where it randomly sends FALSE. Ignore it. */
4394 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4395 {0, 0, FALSE, 0},
4398 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4399 ok(!!d3d, "Failed to create a D3D object.\n");
4400 expect_messages = messages;
4402 wc.cbSize = sizeof(wc);
4403 wc.lpfnWndProc = test_proc;
4404 wc.lpszClassName = "test_reset_fullscreen";
4406 atom = RegisterClassExA(&wc);
4407 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4409 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4410 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4411 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4414 * Create a device in windowed mode.
4415 * Since the device is windowed and we haven't called any methods that
4416 * could show the window (such as ShowWindow or SetWindowPos) yet,
4417 * WM_ACTIVATEAPP will not have been sent.
4419 if (!(device = create_device(d3d, device_window, NULL)))
4421 skip("Unable to create device. Skipping test.\n");
4422 goto cleanup;
4426 * Switch to fullscreen mode.
4427 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4428 * message to be sent.
4430 device_desc.width = registry_mode.dmPelsWidth;
4431 device_desc.height = registry_mode.dmPelsHeight;
4432 device_desc.device_window = device_window;
4433 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4434 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4436 flush_events();
4437 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4438 expect_messages = NULL;
4440 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
4441 mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
4442 for (i = 0; i < mode_count; ++i)
4444 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
4445 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4447 if (d3ddm2.Width != d3ddm.Width || d3ddm2.Height != d3ddm.Height)
4448 break;
4450 if (i == mode_count)
4452 skip("Could not find a suitable display mode.\n");
4453 goto cleanup;
4456 wm_size_received = 0;
4458 /* Fullscreen mode change. */
4459 device_desc.width = d3ddm2.Width;
4460 device_desc.height = d3ddm2.Height;
4461 device_desc.device_window = device_window;
4462 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4463 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4465 flush_events();
4466 ok(!wm_size_received, "Received unexpected WM_SIZE message.\n");
4468 cleanup:
4469 if (device) IDirect3DDevice9_Release(device);
4470 IDirect3D9_Release(d3d);
4471 DestroyWindow(device_window);
4472 device_window = focus_window = NULL;
4473 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4477 static inline void set_fpu_cw(WORD cw)
4479 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4480 #define D3D9_TEST_SET_FPU_CW 1
4481 __asm__ volatile ("fnclex");
4482 __asm__ volatile ("fldcw %0" : : "m" (cw));
4483 #elif defined(__i386__) && defined(_MSC_VER)
4484 #define D3D9_TEST_SET_FPU_CW 1
4485 __asm fnclex;
4486 __asm fldcw cw;
4487 #endif
4490 static inline WORD get_fpu_cw(void)
4492 WORD cw = 0;
4493 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4494 #define D3D9_TEST_GET_FPU_CW 1
4495 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4496 #elif defined(__i386__) && defined(_MSC_VER)
4497 #define D3D9_TEST_GET_FPU_CW 1
4498 __asm fnstcw cw;
4499 #endif
4500 return cw;
4503 static WORD callback_cw, callback_set_cw;
4504 static DWORD callback_tid;
4506 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4508 *out = NULL;
4509 return E_NOINTERFACE;
4512 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4514 callback_cw = get_fpu_cw();
4515 set_fpu_cw(callback_set_cw);
4516 callback_tid = GetCurrentThreadId();
4517 return 2;
4520 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4522 callback_cw = get_fpu_cw();
4523 set_fpu_cw(callback_set_cw);
4524 callback_tid = GetCurrentThreadId();
4525 return 1;
4528 static const IUnknownVtbl dummy_object_vtbl =
4530 dummy_object_QueryInterface,
4531 dummy_object_AddRef,
4532 dummy_object_Release,
4535 static const GUID d3d9_private_data_test_guid =
4537 0xfdb37466,
4538 0x428f,
4539 0x4edf,
4540 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4543 static void test_fpu_setup(void)
4545 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4546 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
4547 IUnknown dummy_object = {&dummy_object_vtbl};
4548 struct device_desc device_desc;
4549 IDirect3DSurface9 *surface;
4550 IDirect3DDevice9 *device;
4551 WORD cw, expected_cw;
4552 HWND window = NULL;
4553 IDirect3D9 *d3d9;
4554 HRESULT hr;
4556 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4557 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4558 ok(!!window, "Failed to create a window.\n");
4559 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4560 ok(!!d3d9, "Failed to create a D3D object.\n");
4562 device_desc.device_window = window;
4563 device_desc.width = 640;
4564 device_desc.height = 480;
4565 device_desc.flags = 0;
4567 set_fpu_cw(0xf60);
4568 cw = get_fpu_cw();
4569 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4571 if (!(device = create_device(d3d9, window, &device_desc)))
4573 skip("Failed to create a 3D device, skipping test.\n");
4574 set_fpu_cw(0x37f);
4575 goto done;
4578 expected_cw = is_64bit ? 0xf60 : 0x7f;
4580 cw = get_fpu_cw();
4581 todo_wine_if(is_64bit)
4582 ok(cw == expected_cw, "cw is %#x, expected %#x.\n", cw, expected_cw);
4584 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4585 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4587 callback_set_cw = 0xf60;
4588 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4589 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4590 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4591 todo_wine_if(is_64bit)
4592 ok(callback_cw == expected_cw, "Callback cw is %#x, expected %#x.\n", callback_cw, expected_cw);
4593 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4594 cw = get_fpu_cw();
4595 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4597 callback_cw = 0;
4598 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4599 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4600 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4601 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4602 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4604 callback_set_cw = 0x7f;
4605 set_fpu_cw(0x7f);
4607 IDirect3DSurface9_Release(surface);
4609 callback_cw = 0;
4610 IDirect3DDevice9_Release(device);
4611 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4612 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4614 cw = get_fpu_cw();
4615 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4616 set_fpu_cw(0xf60);
4617 cw = get_fpu_cw();
4618 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4620 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4621 device = create_device(d3d9, window, &device_desc);
4622 ok(device != NULL, "CreateDevice failed.\n");
4624 cw = get_fpu_cw();
4625 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4627 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4628 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4630 callback_cw = 0;
4631 callback_set_cw = 0x37f;
4632 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4633 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4634 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4635 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4636 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4637 cw = get_fpu_cw();
4638 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4640 IDirect3DSurface9_Release(surface);
4642 callback_cw = 0;
4643 IDirect3DDevice9_Release(device);
4644 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4645 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4647 done:
4648 IDirect3D9_Release(d3d9);
4649 DestroyWindow(window);
4650 #endif
4653 static void test_window_style(void)
4655 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4656 LONG device_style, device_exstyle;
4657 LONG focus_style, focus_exstyle;
4658 struct device_desc device_desc;
4659 LONG style, expected_style;
4660 IDirect3DDevice9 *device;
4661 IDirect3D9 *d3d9;
4662 HRESULT hr;
4663 ULONG ref;
4664 BOOL ret;
4665 static const struct
4667 DWORD device_flags;
4668 LONG style, focus_loss_style, exstyle;
4670 tests[] =
4672 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4673 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4675 unsigned int i;
4677 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4678 ok(!!d3d9, "Failed to create a D3D object.\n");
4679 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4681 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4683 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4684 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4685 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4686 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4688 device_style = GetWindowLongA(device_window, GWL_STYLE);
4689 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4690 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4691 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4693 GetWindowRect(focus_window, &focus_rect);
4694 GetWindowRect(device_window, &device_rect);
4696 device_desc.device_window = device_window;
4697 device_desc.width = registry_mode.dmPelsWidth;
4698 device_desc.height = registry_mode.dmPelsHeight;
4699 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4700 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4702 skip("Failed to create a D3D device, skipping tests.\n");
4703 DestroyWindow(device_window);
4704 DestroyWindow(focus_window);
4705 break;
4708 style = GetWindowLongA(device_window, GWL_STYLE);
4709 expected_style = device_style | tests[i].style;
4710 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4711 expected_style, style, i);
4712 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4713 expected_style = device_exstyle | tests[i].exstyle;
4714 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4715 expected_style, style, i);
4717 style = GetWindowLongA(focus_window, GWL_STYLE);
4718 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4719 focus_style, style, i);
4720 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4721 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4722 focus_exstyle, style, i);
4724 GetWindowRect(device_window, &r);
4725 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4726 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4727 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4728 else
4729 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4730 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4731 GetClientRect(device_window, &r2);
4732 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4733 GetWindowRect(focus_window, &r);
4734 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4735 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4737 device_desc.flags = 0;
4738 hr = reset_device(device, &device_desc);
4739 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4741 style = GetWindowLongA(device_window, GWL_STYLE);
4742 expected_style = device_style | tests[i].style;
4743 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4744 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4745 expected_style, style, i);
4746 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4747 expected_style = device_exstyle | tests[i].exstyle;
4748 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4749 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4750 expected_style, style, i);
4752 style = GetWindowLongA(focus_window, GWL_STYLE);
4753 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4754 focus_style, style, i);
4755 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4756 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4757 focus_exstyle, style, i);
4759 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4760 hr = reset_device(device, &device_desc);
4761 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4762 ret = SetForegroundWindow(GetDesktopWindow());
4763 ok(ret, "Failed to set foreground window.\n");
4765 style = GetWindowLongA(device_window, GWL_STYLE);
4766 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4767 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4768 expected_style, style);
4769 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4770 expected_style = device_exstyle | tests[i].exstyle;
4771 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4772 expected_style, style);
4774 style = GetWindowLongA(focus_window, GWL_STYLE);
4775 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4776 focus_style, style);
4777 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4778 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4779 focus_exstyle, style);
4781 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4782 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4783 * like a good idea to reset it first. */
4784 ShowWindow(focus_window, SW_MINIMIZE);
4785 ShowWindow(focus_window, SW_RESTORE);
4786 ret = SetForegroundWindow(focus_window);
4787 ok(ret, "Failed to set foreground window.\n");
4788 flush_events();
4789 hr = reset_device(device, &device_desc);
4790 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4792 ref = IDirect3DDevice9_Release(device);
4793 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4795 DestroyWindow(device_window);
4796 DestroyWindow(focus_window);
4798 IDirect3D9_Release(d3d9);
4801 static const POINT *expect_pos;
4803 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4805 if (message == WM_MOUSEMOVE)
4807 if (expect_pos && expect_pos->x && expect_pos->y)
4809 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4811 ClientToScreen(window, &p);
4812 if (expect_pos->x == p.x && expect_pos->y == p.y)
4813 ++expect_pos;
4817 return DefWindowProcA(window, message, wparam, lparam);
4820 static void test_cursor_pos(void)
4822 IDirect3DSurface9 *cursor;
4823 IDirect3DDevice9 *device;
4824 WNDCLASSA wc = {0};
4825 IDirect3D9 *d3d9;
4826 UINT refcount;
4827 HWND window;
4828 HRESULT hr;
4829 BOOL ret;
4831 /* Note that we don't check for movement we're not supposed to receive.
4832 * That's because it's hard to distinguish from the user accidentally
4833 * moving the mouse. */
4834 static const POINT points[] =
4836 {50, 50},
4837 {75, 75},
4838 {100, 100},
4839 {125, 125},
4840 {150, 150},
4841 {125, 125},
4842 {150, 150},
4843 {150, 150},
4844 {0, 0},
4847 wc.lpfnWndProc = test_cursor_proc;
4848 wc.lpszClassName = "d3d9_test_cursor_wc";
4849 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4850 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_POPUP | WS_SYSMENU,
4851 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4852 ShowWindow(window, SW_SHOW);
4853 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4854 ok(!!d3d9, "Failed to create a D3D object.\n");
4856 device = create_device(d3d9, window, NULL);
4857 if (!device)
4859 skip("Failed to create a D3D device, skipping tests.\n");
4860 goto done;
4863 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4864 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4865 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4866 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4867 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4868 IDirect3DSurface9_Release(cursor);
4869 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4870 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4872 flush_events();
4873 expect_pos = points;
4875 ret = SetCursorPos(50, 50);
4876 ok(ret, "Failed to set cursor position.\n");
4877 flush_events();
4879 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4880 flush_events();
4881 /* SetCursorPosition() eats duplicates. */
4882 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4883 flush_events();
4885 ret = SetCursorPos(100, 100);
4886 ok(ret, "Failed to set cursor position.\n");
4887 flush_events();
4888 /* Even if the position was set with SetCursorPos(). */
4889 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4890 flush_events();
4892 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4893 flush_events();
4894 ret = SetCursorPos(150, 150);
4895 ok(ret, "Failed to set cursor position.\n");
4896 flush_events();
4897 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4898 flush_events();
4900 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4901 flush_events();
4902 /* SetCursorPos() doesn't. */
4903 ret = SetCursorPos(150, 150);
4904 ok(ret, "Failed to set cursor position.\n");
4905 flush_events();
4907 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4908 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4910 refcount = IDirect3DDevice9_Release(device);
4911 ok(!refcount, "Device has %u references left.\n", refcount);
4912 done:
4913 DestroyWindow(window);
4914 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4915 IDirect3D9_Release(d3d9);
4918 static void test_mode_change(void)
4920 RECT d3d_rect, focus_rect, r;
4921 struct device_desc device_desc;
4922 IDirect3DSurface9 *backbuffer;
4923 IDirect3DDevice9 *device;
4924 D3DSURFACE_DESC desc;
4925 IDirect3D9 *d3d9;
4926 DEVMODEW devmode;
4927 ULONG refcount;
4928 UINT adapter_mode_count, i;
4929 HRESULT hr;
4930 DWORD ret;
4931 LONG change_ret;
4932 D3DDISPLAYMODE d3ddm;
4933 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4935 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4936 ok(!!d3d9, "Failed to create a D3D object.\n");
4938 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4939 for (i = 0; i < adapter_mode_count; ++i)
4941 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4942 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4944 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4945 continue;
4946 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4947 * refuses to create a device at these sizes. */
4948 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4949 continue;
4951 if (!user32_width)
4953 user32_width = d3ddm.Width;
4954 user32_height = d3ddm.Height;
4955 continue;
4958 /* Make sure the d3d mode is smaller in width or height and at most
4959 * equal in the other dimension than the mode passed to
4960 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4961 * the ChangeDisplaySettings parameters + 12. */
4962 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4963 continue;
4964 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4966 d3d_width = d3ddm.Width;
4967 d3d_height = d3ddm.Height;
4968 break;
4970 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4972 d3d_width = user32_width;
4973 d3d_height = user32_height;
4974 user32_width = d3ddm.Width;
4975 user32_height = d3ddm.Height;
4976 break;
4980 if (!d3d_width)
4982 skip("Could not find adequate modes, skipping mode tests.\n");
4983 IDirect3D9_Release(d3d9);
4984 return;
4987 memset(&devmode, 0, sizeof(devmode));
4988 devmode.dmSize = sizeof(devmode);
4989 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4990 devmode.dmPelsWidth = user32_width;
4991 devmode.dmPelsHeight = user32_height;
4992 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4993 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4995 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4996 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4997 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4998 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
5000 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
5001 GetWindowRect(focus_window, &focus_rect);
5003 device_desc.device_window = device_window;
5004 device_desc.width = d3d_width;
5005 device_desc.height = d3d_height;
5006 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5007 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5009 skip("Failed to create a D3D device, skipping tests.\n");
5010 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5011 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5012 goto done;
5015 devmode.dmPelsWidth = user32_width;
5016 devmode.dmPelsHeight = user32_height;
5017 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5018 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5020 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5021 ok(ret, "Failed to get display mode.\n");
5022 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
5023 "Expected resolution %ux%u, got %ux%u.\n",
5024 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
5026 GetWindowRect(device_window, &r);
5027 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
5028 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
5029 GetWindowRect(focus_window, &r);
5030 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
5031 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
5033 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
5034 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
5035 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
5036 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
5037 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
5038 desc.Width, d3d_width);
5039 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
5040 desc.Height, d3d_height);
5041 IDirect3DSurface9_Release(backbuffer);
5043 refcount = IDirect3DDevice9_Release(device);
5044 ok(!refcount, "Device has %u references left.\n", refcount);
5046 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5047 ok(ret, "Failed to get display mode.\n");
5048 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5049 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5050 "Expected resolution %ux%u, got %ux%u.\n",
5051 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5053 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5054 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5056 /* The mode restore also happens when the device was created at the original screen size. */
5058 device_desc.device_window = device_window;
5059 device_desc.width = registry_mode.dmPelsWidth;
5060 device_desc.height = registry_mode.dmPelsHeight;
5061 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5062 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
5064 devmode.dmPelsWidth = user32_width;
5065 devmode.dmPelsHeight = user32_height;
5066 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5067 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5069 refcount = IDirect3DDevice9_Release(device);
5070 ok(!refcount, "Device has %u references left.\n", refcount);
5072 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5073 ok(ret, "Failed to get display mode.\n");
5074 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5075 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5076 "Expected resolution %ux%u, got %ux%u.\n",
5077 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5079 done:
5080 DestroyWindow(device_window);
5081 DestroyWindow(focus_window);
5082 IDirect3D9_Release(d3d9);
5085 static void test_device_window_reset(void)
5087 RECT fullscreen_rect, device_rect, r;
5088 struct device_desc device_desc;
5089 IDirect3DDevice9 *device;
5090 WNDCLASSA wc = {0};
5091 IDirect3D9 *d3d9;
5092 LONG_PTR proc;
5093 HRESULT hr;
5094 ULONG ref;
5096 wc.lpfnWndProc = test_proc;
5097 wc.lpszClassName = "d3d9_test_wndproc_wc";
5098 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5100 focus_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 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5103 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
5104 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5105 ok(!!d3d9, "Failed to create a D3D object.\n");
5107 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
5108 GetWindowRect(device_window, &device_rect);
5110 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5111 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5112 (LONG_PTR)test_proc, proc);
5113 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5114 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5115 (LONG_PTR)test_proc, proc);
5117 device_desc.device_window = NULL;
5118 device_desc.width = registry_mode.dmPelsWidth;
5119 device_desc.height = registry_mode.dmPelsHeight;
5120 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5121 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5123 skip("Failed to create a D3D device, skipping tests.\n");
5124 goto done;
5127 GetWindowRect(focus_window, &r);
5128 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5129 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5130 GetWindowRect(device_window, &r);
5131 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
5132 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
5134 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5135 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5136 (LONG_PTR)test_proc, proc);
5137 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5138 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5140 device_desc.device_window = device_window;
5141 hr = reset_device(device, &device_desc);
5142 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5144 GetWindowRect(focus_window, &r);
5145 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5146 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5147 GetWindowRect(device_window, &r);
5148 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5149 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5151 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5152 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5153 (LONG_PTR)test_proc, proc);
5154 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5155 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5157 ref = IDirect3DDevice9_Release(device);
5158 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5160 done:
5161 IDirect3D9_Release(d3d9);
5162 DestroyWindow(device_window);
5163 DestroyWindow(focus_window);
5164 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
5167 static void test_reset_resources(void)
5169 IDirect3DSurface9 *surface, *rt;
5170 IDirect3DTexture9 *texture;
5171 IDirect3DDevice9 *device;
5172 IDirect3D9 *d3d9;
5173 unsigned int i;
5174 D3DCAPS9 caps;
5175 HWND window;
5176 HRESULT hr;
5177 ULONG ref;
5179 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5180 0, 0, 640, 480, 0, 0, 0, 0);
5181 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5182 ok(!!d3d9, "Failed to create a D3D object.\n");
5184 if (!(device = create_device(d3d9, window, NULL)))
5186 skip("Failed to create a D3D device, skipping tests.\n");
5187 goto done;
5190 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5191 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5193 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5194 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5195 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5196 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5197 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5198 IDirect3DSurface9_Release(surface);
5200 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5202 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5203 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5204 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5205 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5206 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5207 IDirect3DTexture9_Release(texture);
5208 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5209 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5210 IDirect3DSurface9_Release(surface);
5213 hr = reset_device(device, NULL);
5214 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5216 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5217 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5218 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5219 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5220 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5221 IDirect3DSurface9_Release(surface);
5222 IDirect3DSurface9_Release(rt);
5224 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5226 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5227 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5230 ref = IDirect3DDevice9_Release(device);
5231 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5233 done:
5234 IDirect3D9_Release(d3d9);
5235 DestroyWindow(window);
5238 static void test_set_rt_vp_scissor(void)
5240 IDirect3DStateBlock9 *stateblock;
5241 IDirect3DDevice9 *device;
5242 IDirect3DSurface9 *rt;
5243 IDirect3D9 *d3d9;
5244 D3DVIEWPORT9 vp;
5245 UINT refcount;
5246 HWND window;
5247 HRESULT hr;
5248 RECT rect;
5250 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5251 0, 0, 640, 480, 0, 0, 0, 0);
5252 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5253 ok(!!d3d9, "Failed to create a D3D object.\n");
5254 if (!(device = create_device(d3d9, window, NULL)))
5256 skip("Failed to create a D3D device, skipping tests.\n");
5257 DestroyWindow(window);
5258 return;
5261 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5262 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5263 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5265 hr = IDirect3DDevice9_GetViewport(device, &vp);
5266 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5267 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5268 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5269 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5270 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5271 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5272 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5274 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5275 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5276 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5277 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5279 hr = IDirect3DDevice9_BeginStateBlock(device);
5280 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5282 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5283 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5285 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5286 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5287 IDirect3DStateBlock9_Release(stateblock);
5289 hr = IDirect3DDevice9_GetViewport(device, &vp);
5290 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5291 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5292 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5293 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5294 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5295 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5296 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5298 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5299 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5300 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5301 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5303 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5304 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5306 vp.X = 10;
5307 vp.Y = 20;
5308 vp.Width = 30;
5309 vp.Height = 40;
5310 vp.MinZ = 0.25f;
5311 vp.MaxZ = 0.75f;
5312 hr = IDirect3DDevice9_SetViewport(device, &vp);
5313 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5315 SetRect(&rect, 50, 60, 70, 80);
5316 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5317 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5319 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5320 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5322 hr = IDirect3DDevice9_GetViewport(device, &vp);
5323 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5324 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5325 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5326 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5327 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5328 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5329 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5331 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5332 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5333 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5334 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5336 IDirect3DSurface9_Release(rt);
5337 refcount = IDirect3DDevice9_Release(device);
5338 ok(!refcount, "Device has %u references left.\n", refcount);
5339 IDirect3D9_Release(d3d9);
5340 DestroyWindow(window);
5343 static void test_volume_get_container(void)
5345 IDirect3DVolumeTexture9 *texture = NULL;
5346 IDirect3DVolume9 *volume = NULL;
5347 IDirect3DDevice9 *device;
5348 IUnknown *container;
5349 IDirect3D9 *d3d9;
5350 ULONG refcount;
5351 D3DCAPS9 caps;
5352 HWND window;
5353 HRESULT hr;
5355 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5356 0, 0, 640, 480, 0, 0, 0, 0);
5357 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5358 ok(!!d3d9, "Failed to create a D3D object.\n");
5359 if (!(device = create_device(d3d9, window, NULL)))
5361 skip("Failed to create a D3D device, skipping tests.\n");
5362 IDirect3D9_Release(d3d9);
5363 DestroyWindow(window);
5364 return;
5367 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5368 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5369 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5371 skip("No volume texture support, skipping tests.\n");
5372 IDirect3DDevice9_Release(device);
5373 IDirect3D9_Release(d3d9);
5374 DestroyWindow(window);
5375 return;
5378 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5379 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5380 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5381 ok(!!texture, "Got unexpected texture %p.\n", texture);
5383 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5384 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5385 ok(!!volume, "Got unexpected volume %p.\n", volume);
5387 /* These should work... */
5388 container = NULL;
5389 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5390 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5391 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5392 IUnknown_Release(container);
5394 container = NULL;
5395 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5396 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5397 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5398 IUnknown_Release(container);
5400 container = NULL;
5401 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5402 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5403 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5404 IUnknown_Release(container);
5406 container = NULL;
5407 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5408 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5409 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5410 IUnknown_Release(container);
5412 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5413 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5414 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5415 ok(!container, "Got unexpected container %p.\n", container);
5417 IDirect3DVolume9_Release(volume);
5418 IDirect3DVolumeTexture9_Release(texture);
5419 refcount = IDirect3DDevice9_Release(device);
5420 ok(!refcount, "Device has %u references left.\n", refcount);
5421 IDirect3D9_Release(d3d9);
5422 DestroyWindow(window);
5425 static void test_volume_resource(void)
5427 IDirect3DVolumeTexture9 *texture;
5428 IDirect3DResource9 *resource;
5429 IDirect3DVolume9 *volume;
5430 IDirect3DDevice9 *device;
5431 IDirect3D9 *d3d9;
5432 ULONG refcount;
5433 D3DCAPS9 caps;
5434 HWND window;
5435 HRESULT hr;
5437 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5438 0, 0, 640, 480, 0, 0, 0, 0);
5439 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5440 ok(!!d3d9, "Failed to create a D3D object.\n");
5441 if (!(device = create_device(d3d9, window, NULL)))
5443 skip("Failed to create a D3D device, skipping tests.\n");
5444 IDirect3D9_Release(d3d9);
5445 DestroyWindow(window);
5446 return;
5449 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5450 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5451 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5453 skip("No volume texture support, skipping tests.\n");
5454 IDirect3DDevice9_Release(device);
5455 IDirect3D9_Release(d3d9);
5456 DestroyWindow(window);
5457 return;
5460 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5461 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5462 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5463 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5464 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5465 IDirect3DVolumeTexture9_Release(texture);
5467 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5468 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5470 IDirect3DVolume9_Release(volume);
5471 refcount = IDirect3DDevice9_Release(device);
5472 ok(!refcount, "Device has %u references left.\n", refcount);
5473 IDirect3D9_Release(d3d9);
5474 DestroyWindow(window);
5477 static void test_vb_lock_flags(void)
5479 static const struct
5481 DWORD flags;
5482 const char *debug_string;
5483 HRESULT win7_result;
5485 test_data[] =
5487 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5488 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5489 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5490 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5491 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5492 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5493 /* Completely bogus flags aren't an error. */
5494 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5496 IDirect3DVertexBuffer9 *buffer;
5497 IDirect3DDevice9 *device;
5498 IDirect3D9 *d3d9;
5499 unsigned int i;
5500 ULONG refcount;
5501 HWND window;
5502 HRESULT hr;
5503 void *data;
5505 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5506 0, 0, 640, 480, 0, 0, 0, 0);
5507 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5508 ok(!!d3d9, "Failed to create a D3D object.\n");
5509 if (!(device = create_device(d3d9, window, NULL)))
5511 skip("Failed to create a D3D device, skipping tests.\n");
5512 IDirect3D9_Release(d3d9);
5513 DestroyWindow(window);
5514 return;
5517 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5518 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5520 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5522 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5523 /* Windows XP always returns D3D_OK even with flags that don't make
5524 * sense. Windows 7 returns an error. At least one game (Shaiya)
5525 * depends on the Windows XP result, so mark the Windows 7 behavior as
5526 * broken. */
5527 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5528 hr, test_data[i].debug_string);
5529 if (SUCCEEDED(hr))
5531 ok(!!data, "Got unexpected data %p.\n", data);
5532 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5533 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5537 IDirect3DVertexBuffer9_Release(buffer);
5538 refcount = IDirect3DDevice9_Release(device);
5539 ok(!refcount, "Device has %u references left.\n", refcount);
5540 IDirect3D9_Release(d3d9);
5541 DestroyWindow(window);
5544 static const char *debug_d3dpool(D3DPOOL pool)
5546 switch (pool)
5548 case D3DPOOL_DEFAULT:
5549 return "D3DPOOL_DEFAULT";
5550 case D3DPOOL_SYSTEMMEM:
5551 return "D3DPOOL_SYSTEMMEM";
5552 case D3DPOOL_SCRATCH:
5553 return "D3DPOOL_SCRATCH";
5554 case D3DPOOL_MANAGED:
5555 return "D3DPOOL_MANAGED";
5556 default:
5557 return "unknown pool";
5561 static void test_vertex_buffer_alignment(void)
5563 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5564 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5565 IDirect3DVertexBuffer9 *buffer = NULL;
5566 const unsigned int align = 16;
5567 IDirect3DDevice9 *device;
5568 unsigned int i, j;
5569 IDirect3D9 *d3d9;
5570 ULONG refcount;
5571 HWND window;
5572 HRESULT hr;
5573 void *data;
5575 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5576 0, 0, 640, 480, 0, 0, 0, 0);
5577 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5578 ok(!!d3d9, "Failed to create a D3D object.\n");
5579 if (!(device = create_device(d3d9, window, NULL)))
5581 skip("Failed to create a D3D device, skipping tests.\n");
5582 IDirect3D9_Release(d3d9);
5583 DestroyWindow(window);
5584 return;
5587 for (i = 0; i < ARRAY_SIZE(sizes); ++i)
5589 for (j = 0; j < ARRAY_SIZE(pools); ++j)
5591 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5592 if (pools[j] == D3DPOOL_SCRATCH)
5593 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5594 else
5595 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5596 debug_d3dpool(pools[j]), sizes[i], hr);
5597 if (FAILED(hr))
5598 continue;
5600 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5601 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5602 ok(!((DWORD_PTR)data & (align - 1)),
5603 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5604 data, align, sizes[i], debug_d3dpool(pools[j]));
5605 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5606 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5607 IDirect3DVertexBuffer9_Release(buffer);
5611 refcount = IDirect3DDevice9_Release(device);
5612 ok(!refcount, "Device has %u references left.\n", refcount);
5613 IDirect3D9_Release(d3d9);
5614 DestroyWindow(window);
5617 static void test_query_support(void)
5619 static const D3DQUERYTYPE queries[] =
5621 D3DQUERYTYPE_VCACHE,
5622 D3DQUERYTYPE_RESOURCEMANAGER,
5623 D3DQUERYTYPE_VERTEXSTATS,
5624 D3DQUERYTYPE_EVENT,
5625 D3DQUERYTYPE_OCCLUSION,
5626 D3DQUERYTYPE_TIMESTAMP,
5627 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5628 D3DQUERYTYPE_TIMESTAMPFREQ,
5629 D3DQUERYTYPE_PIPELINETIMINGS,
5630 D3DQUERYTYPE_INTERFACETIMINGS,
5631 D3DQUERYTYPE_VERTEXTIMINGS,
5632 D3DQUERYTYPE_PIXELTIMINGS,
5633 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5634 D3DQUERYTYPE_CACHEUTILIZATION,
5636 IDirect3DQuery9 *query = NULL;
5637 IDirect3DDevice9 *device;
5638 IDirect3D9 *d3d9;
5639 unsigned int i;
5640 ULONG refcount;
5641 BOOL supported;
5642 HWND window;
5643 HRESULT hr;
5645 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5646 0, 0, 640, 480, 0, 0, 0, 0);
5647 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5648 ok(!!d3d9, "Failed to create a D3D object.\n");
5649 if (!(device = create_device(d3d9, window, NULL)))
5651 skip("Failed to create a D3D device, skipping tests.\n");
5652 IDirect3D9_Release(d3d9);
5653 DestroyWindow(window);
5654 return;
5657 for (i = 0; i < ARRAY_SIZE(queries); ++i)
5659 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5660 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5662 supported = hr == D3D_OK;
5664 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5665 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5667 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5668 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5670 if (query)
5672 IDirect3DQuery9_Release(query);
5673 query = NULL;
5677 for (i = 0; i < 40; ++i)
5679 /* Windows 10 17.09 (build 16299.19) added an undocumented query with an enum value of 0x16 (=22).
5680 * It returns D3D_OK when asking for support and E_FAIL when trying to actually create it. */
5681 if ((D3DQUERYTYPE_VCACHE <= i && i <= D3DQUERYTYPE_MEMORYPRESSURE) || i == 0x16)
5682 continue;
5684 hr = IDirect3DDevice9_CreateQuery(device, i, NULL);
5685 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5687 query = (IDirect3DQuery9 *)0xdeadbeef;
5688 hr = IDirect3DDevice9_CreateQuery(device, i, &query);
5689 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5690 ok(query == (IDirect3DQuery9 *)0xdeadbeef, "Got unexpected query %p.\n", query);
5693 refcount = IDirect3DDevice9_Release(device);
5694 ok(!refcount, "Device has %u references left.\n", refcount);
5695 IDirect3D9_Release(d3d9);
5696 DestroyWindow(window);
5699 static void test_occlusion_query(void)
5701 static const float quad[] =
5703 -1.0f, -1.0f, 0.0f,
5704 -1.0f, 1.0f, 0.0f,
5705 1.0f, 1.0f, 0.0f,
5706 1.0f, -1.0f, 0.0f,
5708 unsigned int data_size, i, count;
5709 struct device_desc device_desc;
5710 IDirect3DQuery9 *query = NULL;
5711 IDirect3DDevice9 *device;
5712 IDirect3DSurface9 *rt;
5713 IDirect3D9 *d3d9;
5714 D3DVIEWPORT9 vp;
5715 ULONG refcount;
5716 D3DCAPS9 caps;
5717 HWND window;
5718 HRESULT hr;
5719 union
5721 WORD word[4];
5722 DWORD dword[2];
5723 UINT64 uint;
5724 } data, expected;
5725 BOOL broken_occlusion = FALSE;
5726 expected.uint = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5728 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5729 0, 0, 640, 480, 0, 0, 0, 0);
5730 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5731 ok(!!d3d9, "Failed to create a D3D object.\n");
5732 device_desc.device_window = window;
5733 device_desc.width = registry_mode.dmPelsWidth;
5734 device_desc.height = registry_mode.dmPelsHeight;
5735 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5736 if (!(device = create_device(d3d9, window, &device_desc)))
5738 skip("Failed to create a D3D device, skipping tests.\n");
5739 IDirect3D9_Release(d3d9);
5740 DestroyWindow(window);
5741 return;
5744 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5745 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5746 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5747 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5748 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5749 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5751 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5752 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5753 if (!query)
5755 skip("Occlusion queries are not supported, skipping tests.\n");
5756 IDirect3DDevice9_Release(device);
5757 IDirect3D9_Release(d3d9);
5758 DestroyWindow(window);
5759 return;
5762 data_size = IDirect3DQuery9_GetDataSize(query);
5763 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5765 memset(&data, 0xff, sizeof(data));
5766 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5767 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5768 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5769 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5770 ok(data.dword[0] == 0xdddddddd && data.dword[1] == 0xffffffff,
5771 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5773 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
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);
5777 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5778 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5780 data.dword[0] = 0x12345678;
5781 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5782 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5783 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5784 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5785 if (hr == D3D_OK)
5786 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5788 hr = IDirect3DDevice9_BeginScene(device);
5789 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5790 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5791 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5792 hr = IDirect3DDevice9_EndScene(device);
5793 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5795 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5796 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5797 for (i = 0; i < 500; ++i)
5799 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5800 break;
5801 Sleep(10);
5803 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5805 memset(&data, 0xff, sizeof(data));
5806 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5807 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5808 ok(data.dword[0] == expected.dword[0] || broken(!data.dword[0]),
5809 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5810 if (!data.dword[0])
5812 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5813 broken_occlusion = TRUE;
5816 memset(&data, 0xff, sizeof(data));
5817 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5818 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5819 if (!broken_occlusion)
5820 ok(data.word[0] == expected.word[0],
5821 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5822 ok(data.word[1] == 0xffff,
5823 "Data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5825 memset(&data, 0xf0, sizeof(data));
5826 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5827 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5828 if (!broken_occlusion)
5829 ok(data.dword[0] == expected.dword[0],
5830 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5831 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5832 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5833 on AMD and Nvidia respectively). */
5834 if (0)
5836 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5837 data.dword[1]);
5840 memset(&data, 0xff, sizeof(data));
5841 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5842 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5843 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5845 /* This crashes on Windows. */
5846 if (0)
5848 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5849 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5852 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
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);
5856 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5857 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5859 if (broken_occlusion)
5860 goto done;
5862 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5863 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5865 vp.X = 0;
5866 vp.Y = 0;
5867 vp.Width = min(caps.MaxTextureWidth, 8192);
5868 vp.Height = min(caps.MaxTextureHeight, 8192);
5869 vp.MinZ = 0.0f;
5870 vp.MaxZ = 1.0f;
5871 hr = IDirect3DDevice9_SetViewport(device, &vp);
5872 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5874 hr = IDirect3DDevice9_CreateRenderTarget(device, vp.Width, vp.Height,
5875 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5876 if (FAILED(hr))
5878 skip("Failed to create render target (width %u, height %u), hr %#x.\n", vp.Width, vp.Height, hr);
5879 goto done;
5881 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5882 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5883 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5884 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
5885 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5887 expected.uint = vp.Width * vp.Height;
5888 count = ((((UINT64)~0u) + 1) / expected.uint) + 1;
5889 expected.uint *= count;
5891 trace("Expects 0x%08x%08x samples.\n", expected.dword[1], expected.dword[0]);
5893 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5894 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5895 hr = IDirect3DDevice9_BeginScene(device);
5896 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5897 for (i = 0; i < count; i++)
5899 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5900 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5902 hr = IDirect3DDevice9_EndScene(device);
5903 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5904 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5905 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5907 for (i = 0; i < 500; ++i)
5909 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5910 break;
5911 Sleep(10);
5913 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5915 memset(&data, 0xff, sizeof(data));
5916 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5917 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5918 ok((data.dword[0] == expected.dword[0] && data.dword[1] == expected.dword[1])
5919 || (data.dword[0] == 0xffffffff && !data.dword[1])
5920 || broken(data.dword[0] < 0xffffffff && !data.dword[1]),
5921 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5923 IDirect3DSurface9_Release(rt);
5925 done:
5926 IDirect3DQuery9_Release(query);
5927 refcount = IDirect3DDevice9_Release(device);
5928 ok(!refcount, "Device has %u references left.\n", refcount);
5929 IDirect3D9_Release(d3d9);
5930 DestroyWindow(window);
5933 static void test_timestamp_query(void)
5935 static const float quad[] =
5937 -1.0f, -1.0f, 0.0f,
5938 -1.0f, 1.0f, 0.0f,
5939 1.0f, 1.0f, 0.0f,
5940 1.0f, -1.0f, 0.0f,
5942 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5943 unsigned int data_size, i;
5944 IDirect3DDevice9 *device;
5945 IDirect3D9 *d3d9;
5946 ULONG refcount;
5947 HWND window;
5948 HRESULT hr;
5949 DWORD timestamp[2], freq[2];
5950 WORD disjoint[2];
5952 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5953 0, 0, 640, 480, 0, 0, 0, 0);
5954 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5955 ok(!!d3d9, "Failed to create a D3D object.\n");
5956 if (!(device = create_device(d3d9, window, NULL)))
5958 skip("Failed to create a D3D device, skipping tests.\n");
5959 IDirect3D9_Release(d3d9);
5960 DestroyWindow(window);
5961 return;
5964 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5965 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5966 if (FAILED(hr))
5968 skip("Timestamp queries are not supported, skipping tests.\n");
5969 IDirect3DDevice9_Release(device);
5970 IDirect3D9_Release(d3d9);
5971 DestroyWindow(window);
5972 return;
5974 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5975 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5977 memset(freq, 0xff, sizeof(freq));
5978 hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH);
5979 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5980 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5981 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5982 ok(freq[0] == 0xdddddddd && freq[1] == 0xffffffff,
5983 "Got unexpected query result 0x%08x%08x.\n", freq[1], freq[0]);
5985 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5986 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5987 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5988 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5990 memset(disjoint, 0xff, sizeof(disjoint));
5991 hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH);
5992 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5993 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5994 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5995 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xffff,
5996 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
5997 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(DWORD), D3DGETDATA_FLUSH);
5998 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5999 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xdddd,
6000 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
6002 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
6003 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6004 data_size = IDirect3DQuery9_GetDataSize(query);
6005 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
6007 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
6008 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6009 for (i = 0; i < 500; ++i)
6011 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6012 break;
6013 Sleep(10);
6015 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6017 memset(freq, 0xff, sizeof(freq));
6018 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
6019 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6020 ok(freq[1] == 0xffffffff,
6021 "Freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
6022 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
6023 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6024 ok(freq[1] != 0xffffffff, "High bytes of freq were not modified (0x%.8x).\n",
6025 freq[1]);
6027 memset(timestamp, 0xff, sizeof(timestamp));
6028 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
6029 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6030 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6031 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6032 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xffffffff,
6033 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6034 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6035 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6036 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xdddddddd,
6037 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6039 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
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);
6043 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
6044 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6046 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6047 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6049 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6050 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
6051 hr = IDirect3DDevice9_BeginScene(device);
6052 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6053 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6054 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6055 hr = IDirect3DDevice9_EndScene(device);
6056 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6058 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6059 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6060 for (i = 0; i < 500; ++i)
6062 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6063 break;
6064 Sleep(10);
6066 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6068 memset(timestamp, 0xff, sizeof(timestamp));
6069 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6070 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6071 ok(timestamp[1] == 0xffffffff,
6072 "Timestamp was modified outside of the expected size (0x%.8x).\n",
6073 timestamp[1]);
6075 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
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);
6079 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6080 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6082 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
6083 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6084 for (i = 0; i < 500; ++i)
6086 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6087 break;
6088 Sleep(10);
6090 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6092 memset(disjoint, 0xff, sizeof(disjoint));
6093 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
6094 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6095 ok(disjoint[1] == 0xffff,
6096 "Disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
6097 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
6098 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6099 ok(disjoint[1] != 0xffff, "High bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
6101 /* It's not strictly necessary for the TIMESTAMP query to be inside
6102 * a TIMESTAMP_DISJOINT query. */
6103 hr = IDirect3DDevice9_BeginScene(device);
6104 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6105 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6106 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6107 hr = IDirect3DDevice9_EndScene(device);
6108 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6110 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6111 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6112 for (i = 0; i < 500; ++i)
6114 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6115 break;
6116 Sleep(10);
6118 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6119 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6120 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6122 IDirect3DQuery9_Release(query);
6123 IDirect3DQuery9_Release(disjoint_query);
6124 IDirect3DQuery9_Release(freq_query);
6125 refcount = IDirect3DDevice9_Release(device);
6126 ok(!refcount, "Device has %u references left.\n", refcount);
6127 IDirect3D9_Release(d3d9);
6128 DestroyWindow(window);
6131 static void test_get_set_vertex_shader(void)
6133 IDirect3DVertexShader9 *current_shader = NULL;
6134 IDirect3DVertexShader9 *shader = NULL;
6135 const IDirect3DVertexShader9Vtbl *shader_vtbl;
6136 IDirect3DDevice9 *device;
6137 ULONG refcount, i;
6138 IDirect3D9 *d3d;
6139 D3DCAPS9 caps;
6140 HWND window;
6141 HRESULT hr;
6143 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6144 0, 0, 640, 480, 0, 0, 0, 0);
6145 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6146 ok(!!d3d, "Failed to create a D3D object.\n");
6147 if (!(device = create_device(d3d, window, NULL)))
6149 skip("Failed to create a D3D device, skipping tests.\n");
6150 IDirect3D9_Release(d3d);
6151 DestroyWindow(window);
6152 return;
6155 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6156 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6157 if (!(caps.VertexShaderVersion & 0xffff))
6159 skip("No vertex shader support, skipping tests.\n");
6160 IDirect3DDevice9_Release(device);
6161 IDirect3D9_Release(d3d);
6162 DestroyWindow(window);
6163 return;
6166 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
6167 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6168 ok(!!shader, "Got unexpected shader %p.\n", shader);
6170 /* SetVertexShader() should not touch the shader's refcount. */
6171 i = get_refcount((IUnknown *)shader);
6172 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6173 refcount = get_refcount((IUnknown *)shader);
6174 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6175 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6177 /* GetVertexShader() should increase the shader's refcount by one. */
6178 i = refcount + 1;
6179 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
6180 refcount = get_refcount((IUnknown *)shader);
6181 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
6182 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6183 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6184 IDirect3DVertexShader9_Release(current_shader);
6186 /* SetVertexShader() with a bogus shader vtbl */
6187 shader_vtbl = shader->lpVtbl;
6188 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
6189 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6190 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6191 shader->lpVtbl = NULL;
6192 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6193 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6194 shader->lpVtbl = shader_vtbl;
6196 IDirect3DVertexShader9_Release(shader);
6197 refcount = IDirect3DDevice9_Release(device);
6198 ok(!refcount, "Device has %u references left.\n", refcount);
6199 IDirect3D9_Release(d3d);
6200 DestroyWindow(window);
6203 static void test_vertex_shader_constant(void)
6205 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};
6206 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6207 IDirect3DDevice9 *device;
6208 struct device_desc desc;
6209 DWORD consts_swvp;
6210 IDirect3D9 *d3d;
6211 ULONG refcount;
6212 D3DCAPS9 caps;
6213 DWORD consts;
6214 HWND window;
6215 HRESULT hr;
6217 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6218 0, 0, 640, 480, 0, 0, 0, 0);
6219 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6220 ok(!!d3d, "Failed to create a D3D object.\n");
6221 if (!(device = create_device(d3d, window, NULL)))
6223 skip("Failed to create a D3D device, skipping tests.\n");
6224 IDirect3D9_Release(d3d);
6225 DestroyWindow(window);
6226 return;
6229 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6230 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6231 if (!(caps.VertexShaderVersion & 0xffff))
6233 skip("No vertex shader support, skipping tests.\n");
6234 IDirect3DDevice9_Release(device);
6235 IDirect3D9_Release(d3d);
6236 DestroyWindow(window);
6237 return;
6239 consts = caps.MaxVertexShaderConst;
6241 /* A simple check that the stuff works at all. */
6242 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
6243 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6245 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
6246 * consts from MAX - 1. */
6247 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
6248 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6249 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6250 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6251 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6252 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6253 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6254 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6256 /* Constant -1. */
6257 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
6258 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6260 refcount = IDirect3DDevice9_Release(device);
6261 ok(!refcount, "Device has %u references left.\n", refcount);
6263 desc.device_window = window;
6264 desc.width = 640;
6265 desc.height = 480;
6266 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6268 if (!(device = create_device(d3d, window, &desc)))
6270 skip("Failed to create a D3D device, skipping tests.\n");
6271 IDirect3D9_Release(d3d);
6272 DestroyWindow(window);
6273 return;
6275 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6276 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6277 consts_swvp = caps.MaxVertexShaderConst;
6278 todo_wine
6279 ok(consts_swvp == 8192, "Unexpected consts_swvp %u.\n", consts_swvp);
6281 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6282 todo_wine
6283 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6284 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6285 todo_wine
6286 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6287 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6288 todo_wine
6289 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6290 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6291 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6292 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp, c, 1);
6293 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6295 refcount = IDirect3DDevice9_Release(device);
6296 ok(!refcount, "Device has %u references left.\n", refcount);
6298 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6299 if (!(device = create_device(d3d, window, &desc)))
6301 skip("Failed to create a D3D device, skipping tests.\n");
6302 IDirect3D9_Release(d3d);
6303 DestroyWindow(window);
6304 return;
6306 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6307 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6308 ok(consts == caps.MaxVertexShaderConst, "Unexpected caps.MaxVertexShaderConst %u, consts %u.\n",
6309 caps.MaxVertexShaderConst, consts);
6311 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6312 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6313 todo_wine
6314 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6315 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6316 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6318 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 1);
6320 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6321 todo_wine
6322 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6323 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6324 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6326 refcount = IDirect3DDevice9_Release(device);
6327 ok(!refcount, "Device has %u references left.\n", refcount);
6329 IDirect3D9_Release(d3d);
6330 DestroyWindow(window);
6333 static void test_get_set_pixel_shader(void)
6335 IDirect3DPixelShader9 *current_shader = NULL;
6336 IDirect3DPixelShader9 *shader = NULL;
6337 const IDirect3DPixelShader9Vtbl *shader_vtbl;
6338 IDirect3DDevice9 *device;
6339 ULONG refcount, i;
6340 IDirect3D9 *d3d;
6341 D3DCAPS9 caps;
6342 HWND window;
6343 HRESULT hr;
6345 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6346 0, 0, 640, 480, 0, 0, 0, 0);
6347 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6348 ok(!!d3d, "Failed to create a D3D object.\n");
6349 if (!(device = create_device(d3d, window, NULL)))
6351 skip("Failed to create a D3D device, skipping tests.\n");
6352 IDirect3D9_Release(d3d);
6353 DestroyWindow(window);
6354 return;
6357 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6358 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6359 if (!(caps.PixelShaderVersion & 0xffff))
6361 skip("No pixel shader support, skipping tests.\n");
6362 IDirect3DDevice9_Release(device);
6363 IDirect3D9_Release(d3d);
6364 DestroyWindow(window);
6365 return;
6368 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
6369 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6370 ok(!!shader, "Got unexpected shader %p.\n", shader);
6372 /* SetPixelShader() should not touch the shader's refcount. */
6373 i = get_refcount((IUnknown *)shader);
6374 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6375 refcount = get_refcount((IUnknown *)shader);
6376 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6377 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6379 /* GetPixelShader() should increase the shader's refcount by one. */
6380 i = refcount + 1;
6381 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6382 refcount = get_refcount((IUnknown *)shader);
6383 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6384 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6385 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6386 IDirect3DPixelShader9_Release(current_shader);
6388 /* SetPixelShader() with a bogus shader vtbl */
6389 shader_vtbl = shader->lpVtbl;
6390 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6391 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6392 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6393 shader->lpVtbl = NULL;
6394 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6395 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6396 shader->lpVtbl = shader_vtbl;
6398 IDirect3DPixelShader9_Release(shader);
6399 refcount = IDirect3DDevice9_Release(device);
6400 ok(!refcount, "Device has %u references left.\n", refcount);
6401 IDirect3D9_Release(d3d);
6402 DestroyWindow(window);
6405 static void test_pixel_shader_constant(void)
6407 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};
6408 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6409 IDirect3DDevice9 *device;
6410 DWORD consts = 0;
6411 IDirect3D9 *d3d;
6412 ULONG refcount;
6413 D3DCAPS9 caps;
6414 HWND window;
6415 HRESULT hr;
6417 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6418 0, 0, 640, 480, 0, 0, 0, 0);
6419 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6420 ok(!!d3d, "Failed to create a D3D object.\n");
6421 if (!(device = create_device(d3d, window, NULL)))
6423 skip("Failed to create a D3D device, skipping tests.\n");
6424 IDirect3D9_Release(d3d);
6425 DestroyWindow(window);
6426 return;
6429 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6430 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6431 if (!(caps.PixelShaderVersion & 0xffff))
6433 skip("No pixel shader support, skipping tests.\n");
6434 IDirect3DDevice9_Release(device);
6435 IDirect3D9_Release(d3d);
6436 DestroyWindow(window);
6437 return;
6440 /* A simple check that the stuff works at all. */
6441 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6442 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6444 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6445 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6446 consts = consts - 1;
6447 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6449 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6450 * pointless given the way the constant limit was determined. */
6451 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6452 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6454 /* Constant -1. */
6455 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6456 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6458 refcount = IDirect3DDevice9_Release(device);
6459 ok(!refcount, "Device has %u references left.\n", refcount);
6460 IDirect3D9_Release(d3d);
6461 DestroyWindow(window);
6464 static void test_unsupported_shaders(void)
6466 static const DWORD vs_3_0[] =
6468 0xfffe0300, /* vs_3_0 */
6469 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6470 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6471 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6472 0x0000ffff, /* end */
6475 #if 0
6476 float4 main(const float4 color : COLOR) : SV_TARGET
6478 float4 o;
6480 o = color;
6482 return o;
6484 #endif
6485 static const DWORD ps_4_0[] =
6487 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6488 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6489 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6490 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6491 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6492 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6493 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6494 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6495 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6496 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6497 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6498 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6499 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6500 0x00000000, 0x00000000, 0x00000000,
6502 #if 0
6503 vs_1_1
6504 dcl_position v0
6505 def c255, 1.0, 1.0, 1.0, 1.0
6506 add r0, v0, c255
6507 mov oPos, r0
6508 #endif
6509 static const DWORD vs_1_255[] =
6511 0xfffe0101,
6512 0x0000001f, 0x80000000, 0x900f0000,
6513 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6514 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6515 0x00000001, 0xc00f0000, 0x80e40000,
6516 0x0000ffff
6518 #if 0
6519 vs_1_1
6520 dcl_position v0
6521 def c256, 1.0, 1.0, 1.0, 1.0
6522 add r0, v0, c256
6523 mov oPos, r0
6524 #endif
6525 static const DWORD vs_1_256[] =
6527 0xfffe0101,
6528 0x0000001f, 0x80000000, 0x900f0000,
6529 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6530 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6531 0x00000001, 0xc00f0000, 0x80e40000,
6532 0x0000ffff
6534 #if 0
6535 vs_3_0
6536 dcl_position v0
6537 dcl_position o0
6538 def c256, 1.0, 1.0, 1.0, 1.0
6539 add r0, v0, c256
6540 mov o0, r0
6541 #endif
6542 static const DWORD vs_3_256[] =
6544 0xfffe0300,
6545 0x0200001f, 0x80000000, 0x900f0000,
6546 0x0200001f, 0x80000000, 0xe00f0000,
6547 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6548 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6549 0x02000001, 0xe00f0000, 0x80e40000,
6550 0x0000ffff
6552 #if 0
6553 /* This shader source generates syntax errors with the native shader assembler
6554 * due to the constant register index values.
6555 * The bytecode was modified by hand to use the intended values. */
6556 vs_3_0
6557 dcl_position v0
6558 dcl_position o0
6559 defi i16, 1, 1, 1, 1
6560 rep i16
6561 add r0, r0, v0
6562 endrep
6563 mov o0, r0
6564 #endif
6565 static const DWORD vs_3_i16[] =
6567 0xfffe0300,
6568 0x0200001f, 0x80000000, 0x900f0000,
6569 0x0200001f, 0x80000000, 0xe00f0000,
6570 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6571 0x01000026, 0xf0e40010,
6572 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6573 0x00000027,
6574 0x02000001, 0xe00f0000, 0x80e40000,
6575 0x0000ffff
6577 #if 0
6578 /* This shader source generates syntax errors with the native shader assembler
6579 * due to the constant register index values.
6580 * The bytecode was modified by hand to use the intended values. */
6581 vs_3_0
6582 dcl_position v0
6583 dcl_position o0
6584 defb b16, true
6585 mov r0, v0
6586 if b16
6587 add r0, r0, v0
6588 endif
6589 mov o0, r0
6590 #endif
6591 static const DWORD vs_3_b16[] =
6593 0xfffe0300,
6594 0x0200001f, 0x80000000, 0x900f0000,
6595 0x0200001f, 0x80000000, 0xe00f0000,
6596 0x0200002f, 0xe00f0810, 0x00000001,
6597 0x02000001, 0x800f0000, 0x90e40000,
6598 0x01000028, 0xe0e40810,
6599 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6600 0x0000002b,
6601 0x02000001, 0xe00f0000, 0x80e40000,
6602 0x0000ffff
6604 #if 0
6605 /* This shader source generates syntax errors with the native shader assembler
6606 * due to the constant register index values.
6607 * The bytecode was modified by hand to use the intended values. */
6608 ps_1_1
6609 def c8, 1.0, 1.0, 1.0, 1.0
6610 add r0, v0, c8
6611 #endif
6612 static const DWORD ps_1_8[] =
6614 0xffff0101,
6615 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6616 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6617 0x0000ffff
6619 #if 0
6620 /* This shader source generates syntax errors with the native shader assembler
6621 * due to the constant register index values.
6622 * The bytecode was modified by hand to use the intended values. */
6623 ps_2_0
6624 def c32, 1.0, 1.0, 1.0, 1.0
6625 add oC0, v0, c32
6626 #endif
6627 static const DWORD ps_2_32[] =
6629 0xffff0200,
6630 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6631 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6632 0x0000ffff
6634 #if 0
6635 /* This shader source generates syntax errors with the native shader assembler
6636 * due to the constant register index values.
6637 * The bytecode was modified by hand to use the intended values. */
6638 ps_3_0
6639 dcl_color0 v0
6640 def c224, 1.0, 1.0, 1.0, 1.0
6641 add oC0, v0, c224
6642 #endif
6643 static const DWORD ps_3_224[] =
6645 0xffff0300,
6646 0x0200001f, 0x8000000a, 0x900f0000,
6647 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6648 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6649 0x0000ffff
6651 #if 0
6652 /* This shader source generates syntax errors with the native shader assembler
6653 * due to the constant register index values.
6654 * The bytecode was modified by hand to use the intended values. */
6655 ps_2_0
6656 defb b0, true
6657 defi i0, 1, 1, 1, 1
6658 rep i0
6659 if b0
6660 add r0, r0, v0
6661 endif
6662 endrep
6663 mov oC0, r0
6664 #endif
6665 static const DWORD ps_2_0_boolint[] =
6667 0xffff0200,
6668 0x0200002f, 0xe00f0800, 0x00000001,
6669 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6670 0x01000026, 0xf0e40000,
6671 0x01000028, 0xe0e40800,
6672 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6673 0x0000002b,
6674 0x00000027,
6675 0x02000001, 0x800f0800, 0x80e40000,
6676 0x0000ffff
6679 IDirect3DVertexShader9 *vs = NULL;
6680 IDirect3DPixelShader9 *ps = NULL;
6681 IDirect3DDevice9 *device;
6682 struct device_desc desc;
6683 IDirect3D9 * d3d;
6684 ULONG refcount;
6685 D3DCAPS9 caps;
6686 HWND window;
6687 HRESULT hr;
6689 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6690 0, 0, 640, 480, 0, 0, 0, 0);
6691 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6692 ok(!!d3d, "Failed to create a D3D object.\n");
6693 if (!(device = create_device(d3d, window, NULL)))
6695 skip("Failed to create a D3D device, skipping tests.\n");
6696 IDirect3D9_Release(d3d);
6697 DestroyWindow(window);
6698 return;
6701 /* These should always fail, regardless of supported shader version. */
6702 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6703 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6704 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6705 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6706 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6707 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6709 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6710 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6711 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6713 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6714 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6715 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6717 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6718 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6720 else
6722 skip("GPU supports SM2+, skipping SM1 test.\n");
6725 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6727 else
6729 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6731 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6732 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6733 IDirect3DVertexShader9_Release(vs);
6734 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6735 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6736 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6737 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6738 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6739 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6740 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6741 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6744 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6746 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6747 goto cleanup;
6749 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6750 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6751 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6752 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6753 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6754 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6755 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6756 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6757 if (ps)
6758 IDirect3DPixelShader9_Release(ps);
6760 refcount = IDirect3DDevice9_Release(device);
6761 ok(!refcount, "Device has %u references left.\n", refcount);
6763 desc.device_window = window;
6764 desc.width = 640;
6765 desc.height = 480;
6766 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6768 if (!(device = create_device(d3d, window, &desc)))
6770 skip("Failed to create a D3D device, skipping tests.\n");
6771 IDirect3D9_Release(d3d);
6772 DestroyWindow(window);
6773 return;
6776 vs = NULL;
6777 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6778 todo_wine
6779 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6780 if (vs)
6781 IDirect3DVertexShader9_Release(vs);
6782 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6783 todo_wine
6784 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6785 if (vs)
6786 IDirect3DVertexShader9_Release(vs);
6788 refcount = IDirect3DDevice9_Release(device);
6789 ok(!refcount, "Device has %u references left.\n", refcount);
6791 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6792 if (!(device = create_device(d3d, window, &desc)))
6794 skip("Failed to create a D3D device, skipping tests.\n");
6795 IDirect3D9_Release(d3d);
6796 DestroyWindow(window);
6797 return;
6799 hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6800 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6802 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6803 todo_wine
6804 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6805 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6806 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6807 if (vs)
6808 IDirect3DVertexShader9_Release(vs);
6810 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6811 todo_wine
6812 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6813 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6814 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6815 if (vs)
6816 IDirect3DVertexShader9_Release(vs);
6818 cleanup:
6819 refcount = IDirect3DDevice9_Release(device);
6820 ok(!refcount, "Device has %u references left.\n", refcount);
6821 IDirect3D9_Release(d3d);
6822 DestroyWindow(window);
6825 /* Test the default texture stage state values */
6826 static void test_texture_stage_states(void)
6828 IDirect3DDevice9 *device;
6829 IDirect3D9 *d3d;
6830 unsigned int i;
6831 ULONG refcount;
6832 D3DCAPS9 caps;
6833 DWORD value;
6834 HWND window;
6835 HRESULT hr;
6837 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6838 0, 0, 640, 480, 0, 0, 0, 0);
6839 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6840 ok(!!d3d, "Failed to create a D3D object.\n");
6841 if (!(device = create_device(d3d, window, NULL)))
6843 skip("Failed to create a D3D device, skipping tests.\n");
6844 IDirect3D9_Release(d3d);
6845 DestroyWindow(window);
6846 return;
6849 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6850 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6852 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6854 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6855 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6856 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6857 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6858 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6859 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6860 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6861 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6862 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6863 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6864 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6865 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6866 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6867 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6868 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6869 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6870 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6871 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6872 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6873 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6874 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6875 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6876 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6877 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6878 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6879 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6880 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6881 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6882 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6883 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6884 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6885 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6886 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6887 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6888 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6889 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6890 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6891 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6892 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6893 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6894 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6895 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6896 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6897 ok(value == D3DTTFF_DISABLE,
6898 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6899 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6900 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6901 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6902 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6903 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6904 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6905 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6906 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6907 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6908 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6909 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6910 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6913 refcount = IDirect3DDevice9_Release(device);
6914 ok(!refcount, "Device has %u references left.\n", refcount);
6915 IDirect3D9_Release(d3d);
6916 DestroyWindow(window);
6919 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6921 IDirect3DCubeTexture9 *texture;
6922 IDirect3D9 *d3d;
6923 HRESULT hr;
6925 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6926 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6927 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6928 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6929 IDirect3D9_Release(d3d);
6930 if (hr != D3D_OK)
6932 skip("No cube mipmap generation support, skipping tests.\n");
6933 return;
6936 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6937 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6938 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6939 IDirect3DCubeTexture9_Release(texture);
6941 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6942 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6943 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6944 IDirect3DCubeTexture9_Release(texture);
6947 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6949 IDirect3DCubeTexture9 *texture;
6950 IDirect3DSurface9 *surface;
6951 D3DSURFACE_DESC desc;
6952 DWORD levels;
6953 HRESULT hr;
6954 D3DCAPS9 caps;
6956 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6957 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6958 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6959 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6961 skip("Failed to create cube texture, skipping tests.\n");
6962 return;
6965 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6966 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6967 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6968 else
6969 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6971 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6972 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6973 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6974 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6975 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6976 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6978 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6979 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6980 IDirect3DSurface9_Release(surface);
6981 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6982 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6983 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6984 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6986 IDirect3DCubeTexture9_Release(texture);
6989 static void test_cube_textures(void)
6991 IDirect3DCubeTexture9 *texture;
6992 IDirect3DDevice9 *device;
6993 IDirect3D9 *d3d;
6994 ULONG refcount;
6995 D3DCAPS9 caps;
6996 HWND window;
6997 HRESULT hr;
6999 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7000 0, 0, 640, 480, 0, 0, 0, 0);
7001 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7002 ok(!!d3d, "Failed to create a D3D object.\n");
7003 if (!(device = create_device(d3d, window, NULL)))
7005 skip("Failed to create a D3D device, skipping tests.\n");
7006 IDirect3D9_Release(d3d);
7007 DestroyWindow(window);
7008 return;
7011 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7012 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7014 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7016 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7017 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
7018 IDirect3DCubeTexture9_Release(texture);
7019 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7020 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
7021 IDirect3DCubeTexture9_Release(texture);
7022 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7023 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
7024 IDirect3DCubeTexture9_Release(texture);
7026 else
7028 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7029 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
7030 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7031 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
7032 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7033 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
7035 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
7036 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
7037 IDirect3DCubeTexture9_Release(texture);
7039 test_cube_texture_mipmap_gen(device);
7040 test_cube_texture_levels(device);
7042 refcount = IDirect3DDevice9_Release(device);
7043 ok(!refcount, "Device has %u references left.\n", refcount);
7044 IDirect3D9_Release(d3d);
7045 DestroyWindow(window);
7048 static void test_mipmap_gen(void)
7050 static const D3DFORMAT formats[] =
7052 D3DFMT_A8R8G8B8,
7053 D3DFMT_X8R8G8B8,
7054 D3DFMT_A1R5G5B5,
7055 D3DFMT_A4R4G4B4,
7056 D3DFMT_A8,
7057 D3DFMT_L8,
7058 D3DFMT_A8L8,
7059 D3DFMT_V8U8,
7060 D3DFMT_DXT5,
7062 D3DTEXTUREFILTERTYPE filter_type;
7063 IDirect3DTexture9 *texture;
7064 IDirect3DSurface9 *surface;
7065 IDirect3DDevice9 *device;
7066 unsigned int i, count;
7067 D3DSURFACE_DESC desc;
7068 D3DLOCKED_RECT lr;
7069 IDirect3D9 *d3d;
7070 BOOL renderable;
7071 ULONG refcount;
7072 DWORD levels;
7073 HWND window;
7074 HRESULT hr;
7076 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7077 ok(!!d3d, "Failed to create a D3D object.\n");
7079 for (i = 0; i < ARRAY_SIZE(formats); ++i)
7081 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7082 0, D3DRTYPE_TEXTURE, formats[i]);
7083 if (FAILED(hr))
7085 skip("Skipping unsupported format %#x.\n", formats[i]);
7086 continue;
7088 renderable = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7089 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, formats[i]));
7090 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7091 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, formats[i]);
7092 ok((hr == D3D_OK && renderable) || hr == D3DOK_NOAUTOGEN,
7093 "Got unexpected hr %#x for %srenderable format %#x.\n",
7094 hr, renderable ? "" : "non", formats[i]);
7097 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7098 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK)
7100 skip("No mipmap generation support, skipping tests.\n");
7101 IDirect3D9_Release(d3d);
7102 return;
7105 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7106 0, 0, 640, 480, 0, 0, 0, 0);
7107 if (!(device = create_device(d3d, window, NULL)))
7109 skip("Failed to create a D3D device, skipping tests.\n");
7110 IDirect3D9_Release(d3d);
7111 DestroyWindow(window);
7112 return;
7115 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
7116 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7117 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7118 IDirect3DTexture9_Release(texture);
7120 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7121 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7122 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7124 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7125 ok(filter_type == D3DTEXF_LINEAR, "Got unexpected filter_type %#x.\n", filter_type);
7126 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
7127 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7128 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
7129 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7130 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7131 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
7132 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
7133 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7135 levels = IDirect3DTexture9_GetLevelCount(texture);
7136 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7138 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
7140 surface = NULL;
7141 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
7142 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7143 if (surface)
7144 IDirect3DSurface9_Release(surface);
7146 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
7147 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7149 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
7150 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7151 if (SUCCEEDED(hr))
7153 hr = IDirect3DTexture9_UnlockRect(texture, i);
7154 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7157 IDirect3DTexture9_Release(texture);
7159 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
7160 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7161 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7162 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
7163 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7164 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7166 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
7167 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7168 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7169 levels = IDirect3DTexture9_GetLevelCount(texture);
7170 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7171 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7172 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7173 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7174 IDirect3DTexture9_Release(texture);
7176 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7177 D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, 0);
7178 ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr);
7180 for (i = 0; i < ARRAY_SIZE(formats); ++i)
7182 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7183 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, formats[i]);
7184 if (SUCCEEDED(hr))
7186 /* i.e. there is no difference between the D3D_OK and the
7187 * D3DOK_NOAUTOGEN cases. */
7188 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7189 formats[i], D3DPOOL_DEFAULT, &texture, 0);
7190 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7191 count = IDirect3DTexture9_GetLevelCount(texture);
7192 ok(count == 1, "Unexpected level count %u.\n", count);
7193 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7194 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7195 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7196 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7197 ok(filter_type == D3DTEXF_LINEAR, "Got unexpected filter_type %#x.\n", filter_type);
7198 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
7199 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7200 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7201 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
7202 IDirect3DTexture9_Release(texture);
7206 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
7207 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_WRAPANDMIP, D3DRTYPE_TEXTURE, D3DFMT_D16);
7208 if (hr == D3D_OK)
7210 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7211 D3DFMT_D16, D3DPOOL_DEFAULT, &texture, 0);
7212 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7213 count = IDirect3DTexture9_GetLevelCount(texture);
7214 ok(count == 7, "Unexpected level count %u.\n", count);
7215 IDirect3DTexture9_Release(texture);
7217 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
7218 D3DFMT_X8R8G8B8, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_D16);
7219 ok(hr == D3DOK_NOAUTOGEN, "Unexpected hr %#x.\n", hr);
7220 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7221 D3DFMT_D16, D3DPOOL_DEFAULT, &texture, 0);
7222 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7223 count = IDirect3DTexture9_GetLevelCount(texture);
7224 ok(count == 1, "Unexpected level count %u.\n", count);
7225 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7226 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7227 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7228 IDirect3DTexture9_Release(texture);
7230 else
7232 skip("Mipmapping not supported for D3DFMT_D16, skipping test.\n");
7235 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7236 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&texture, 0);
7237 ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr);
7239 refcount = IDirect3DDevice9_Release(device);
7240 ok(!refcount, "Device has %u references left.\n", refcount);
7241 IDirect3D9_Release(d3d);
7242 DestroyWindow(window);
7245 static void test_filter(void)
7247 static const struct
7249 DWORD magfilter, minfilter, mipfilter;
7250 BOOL has_texture;
7251 HRESULT result;
7253 tests[] =
7255 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7256 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7257 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7258 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
7259 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
7261 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7262 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7263 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
7264 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
7266 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7267 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7268 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
7269 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
7270 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
7272 IDirect3DTexture9 *texture;
7273 IDirect3DDevice9 *device;
7274 IDirect3D9 *d3d;
7275 unsigned int i;
7276 ULONG refcount;
7277 DWORD passes;
7278 HWND window;
7279 HRESULT hr;
7281 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7282 ok(!!d3d, "Failed to create a D3D object.\n");
7284 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7285 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7287 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
7288 IDirect3D9_Release(d3d);
7289 return;
7292 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7293 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7295 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
7296 IDirect3D9_Release(d3d);
7297 return;
7300 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7301 0, 0, 640, 480, 0, 0, 0, 0);
7302 if (!(device = create_device(d3d, window, NULL)))
7304 skip("Failed to create a D3D device, skipping tests.\n");
7305 IDirect3D9_Release(d3d);
7306 DestroyWindow(window);
7307 return;
7310 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
7311 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
7312 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7314 /* Needed for ValidateDevice(). */
7315 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7316 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
7318 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7320 if (tests[i].has_texture)
7322 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
7323 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7325 else
7327 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7328 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7331 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
7332 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7333 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
7334 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7335 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
7336 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7338 passes = 0xdeadbeef;
7339 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
7340 ok(hr == tests[i].result,
7341 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
7342 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
7343 tests[i].mipfilter, tests[i].has_texture);
7344 if (SUCCEEDED(hr))
7345 ok(!!passes, "Got unexpected passes %#x.\n", passes);
7346 else
7347 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
7350 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7351 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7352 IDirect3DTexture9_Release(texture);
7354 refcount = IDirect3DDevice9_Release(device);
7355 ok(!refcount, "Device has %u references left.\n", refcount);
7356 IDirect3D9_Release(d3d);
7357 DestroyWindow(window);
7360 static void test_get_set_texture(void)
7362 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
7363 IDirect3DBaseTexture9 *texture;
7364 IDirect3DDevice9 *device;
7365 IDirect3D9 *d3d;
7366 ULONG refcount;
7367 HWND window;
7368 HRESULT hr;
7370 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7371 0, 0, 640, 480, 0, 0, 0, 0);
7372 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7373 ok(!!d3d, "Failed to create a D3D object.\n");
7374 if (!(device = create_device(d3d, window, NULL)))
7376 skip("Failed to create a D3D device, skipping tests.\n");
7377 IDirect3D9_Release(d3d);
7378 DestroyWindow(window);
7379 return;
7382 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
7383 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7384 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7385 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
7386 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7387 ok(!texture, "Got unexpected texture %p.\n", texture);
7389 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
7390 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
7391 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7392 texture_vtbl = texture->lpVtbl;
7393 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
7394 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7395 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7396 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7397 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7398 texture->lpVtbl = NULL;
7399 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7400 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7401 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7402 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7403 texture->lpVtbl = texture_vtbl;
7404 IDirect3DBaseTexture9_Release(texture);
7406 refcount = IDirect3DDevice9_Release(device);
7407 ok(!refcount, "Device has %u references left.\n", refcount);
7408 IDirect3D9_Release(d3d);
7409 DestroyWindow(window);
7412 static void test_lod(void)
7414 IDirect3DTexture9 *texture;
7415 IDirect3DDevice9 *device;
7416 IDirect3D9 *d3d;
7417 ULONG refcount;
7418 HWND window;
7419 HRESULT hr;
7420 DWORD ret;
7422 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7423 0, 0, 640, 480, 0, 0, 0, 0);
7424 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7425 ok(!!d3d, "Failed to create a D3D object.\n");
7426 if (!(device = create_device(d3d, window, NULL)))
7428 skip("Failed to create a D3D device, skipping tests.\n");
7429 IDirect3D9_Release(d3d);
7430 DestroyWindow(window);
7431 return;
7434 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
7435 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7436 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7438 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
7439 * return a HRESULT, so it can't return a normal error. Instead, the call
7440 * is simply ignored. */
7441 ret = IDirect3DTexture9_SetLOD(texture, 0);
7442 ok(!ret, "Got unexpected ret %u.\n", ret);
7443 ret = IDirect3DTexture9_SetLOD(texture, 1);
7444 ok(!ret, "Got unexpected ret %u.\n", ret);
7445 ret = IDirect3DTexture9_SetLOD(texture, 2);
7446 ok(!ret, "Got unexpected ret %u.\n", ret);
7447 ret = IDirect3DTexture9_GetLOD(texture);
7448 ok(!ret, "Got unexpected ret %u.\n", ret);
7450 IDirect3DTexture9_Release(texture);
7451 refcount = IDirect3DDevice9_Release(device);
7452 ok(!refcount, "Device has %u references left.\n", refcount);
7453 IDirect3D9_Release(d3d);
7454 DestroyWindow(window);
7457 static void test_surface_get_container(void)
7459 IDirect3DTexture9 *texture = NULL;
7460 IDirect3DSurface9 *surface = NULL;
7461 IDirect3DDevice9 *device;
7462 IUnknown *container;
7463 IDirect3D9 *d3d;
7464 ULONG refcount;
7465 HWND window;
7466 HRESULT hr;
7468 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7469 0, 0, 640, 480, 0, 0, 0, 0);
7470 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7471 ok(!!d3d, "Failed to create a D3D object.\n");
7472 if (!(device = create_device(d3d, window, NULL)))
7474 skip("Failed to create a D3D device, skipping tests.\n");
7475 IDirect3D9_Release(d3d);
7476 DestroyWindow(window);
7477 return;
7480 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
7481 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7482 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7483 ok(!!texture, "Got unexpected texture %p.\n", texture);
7485 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7486 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7487 ok(!!surface, "Got unexpected surface %p.\n", surface);
7489 /* These should work... */
7490 container = NULL;
7491 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
7492 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7493 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7494 IUnknown_Release(container);
7496 container = NULL;
7497 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
7498 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7499 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7500 IUnknown_Release(container);
7502 container = NULL;
7503 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
7504 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7505 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7506 IUnknown_Release(container);
7508 container = NULL;
7509 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
7510 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7511 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7512 IUnknown_Release(container);
7514 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
7515 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
7516 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7517 ok(!container, "Got unexpected container %p.\n", container);
7519 IDirect3DSurface9_Release(surface);
7520 IDirect3DTexture9_Release(texture);
7521 refcount = IDirect3DDevice9_Release(device);
7522 ok(!refcount, "Device has %u references left.\n", refcount);
7523 IDirect3D9_Release(d3d);
7524 DestroyWindow(window);
7527 static void test_surface_alignment(void)
7529 IDirect3DSurface9 *surface;
7530 IDirect3DDevice9 *device;
7531 D3DLOCKED_RECT lr;
7532 unsigned int i, j;
7533 IDirect3D9 *d3d;
7534 ULONG refcount;
7535 HWND window;
7536 HRESULT hr;
7538 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7539 0, 0, 640, 480, 0, 0, 0, 0);
7540 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7541 ok(!!d3d, "Failed to create a D3D object.\n");
7542 if (!(device = create_device(d3d, window, NULL)))
7544 skip("Failed to create a D3D device, skipping tests.\n");
7545 IDirect3D9_Release(d3d);
7546 DestroyWindow(window);
7547 return;
7550 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7551 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7552 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7553 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7555 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7556 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7557 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7558 /* Some applications also depend on the exact pitch, rather than just the
7559 * alignment. */
7560 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7561 hr = IDirect3DSurface9_UnlockRect(surface);
7562 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7563 IDirect3DSurface9_Release(surface);
7565 for (i = 0; i < 5; ++i)
7567 IDirect3DTexture9 *texture;
7568 unsigned int level_count;
7569 D3DSURFACE_DESC desc;
7570 int expected_pitch;
7572 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7573 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7574 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7575 if (FAILED(hr))
7577 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7578 continue;
7581 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7582 for (j = 0; j < level_count; ++j)
7584 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7585 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7586 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7587 hr = IDirect3DTexture9_UnlockRect(texture, j);
7588 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7590 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7591 if (i > 0)
7592 expected_pitch <<= 1;
7593 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7594 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7596 IDirect3DTexture9_Release(texture);
7599 refcount = IDirect3DDevice9_Release(device);
7600 ok(!refcount, "Device has %u references left.\n", refcount);
7601 IDirect3D9_Release(d3d);
7602 DestroyWindow(window);
7605 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7606 * different from regular formats. This test verifies we return the correct
7607 * memory offsets. */
7608 static void test_lockrect_offset(void)
7610 static const struct
7612 D3DFORMAT format;
7613 const char *name;
7614 unsigned int block_width;
7615 unsigned int block_height;
7616 unsigned int block_size;
7618 dxt_formats[] =
7620 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7621 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7622 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7623 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7624 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7625 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7626 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7628 unsigned int expected_offset, offset, i;
7629 const RECT rect = {60, 60, 68, 68};
7630 IDirect3DSurface9 *surface;
7631 D3DLOCKED_RECT locked_rect;
7632 IDirect3DDevice9 *device;
7633 int expected_pitch;
7634 IDirect3D9 *d3d;
7635 ULONG refcount;
7636 HWND window;
7637 BYTE *base;
7638 HRESULT hr;
7640 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7641 0, 0, 640, 480, 0, 0, 0, 0);
7642 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7643 ok(!!d3d, "Failed to create a D3D object.\n");
7644 if (!(device = create_device(d3d, window, NULL)))
7646 skip("Failed to create a D3D device, skipping tests.\n");
7647 IDirect3D9_Release(d3d);
7648 DestroyWindow(window);
7649 return;
7652 for (i = 0; i < ARRAY_SIZE(dxt_formats); ++i)
7654 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7655 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7657 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7658 continue;
7661 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7662 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7663 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7665 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7666 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7668 base = locked_rect.pBits;
7669 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7670 * dxt_formats[i].block_size;
7671 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7672 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7674 hr = IDirect3DSurface9_UnlockRect(surface);
7675 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7677 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7678 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7680 offset = (BYTE *)locked_rect.pBits - base;
7681 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7682 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7683 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7684 offset, dxt_formats[i].name, expected_offset);
7686 hr = IDirect3DSurface9_UnlockRect(surface);
7687 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7689 IDirect3DSurface9_Release(surface);
7692 refcount = IDirect3DDevice9_Release(device);
7693 ok(!refcount, "Device has %u references left.\n", refcount);
7694 IDirect3D9_Release(d3d);
7695 DestroyWindow(window);
7698 static void test_lockrect_invalid(void)
7700 static const struct
7702 RECT rect;
7703 HRESULT win7_result;
7705 test_data[] =
7707 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7708 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7709 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7710 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7711 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7712 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7713 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7714 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7715 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7716 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7717 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7718 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7719 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7721 static const RECT test_rect_2 = {0, 0, 8, 8};
7722 IDirect3DSurface9 *surface = NULL;
7723 D3DLOCKED_RECT locked_rect;
7724 IDirect3DDevice9 *device;
7725 IDirect3DTexture9 *texture;
7726 IDirect3DCubeTexture9 *cube_texture;
7727 HRESULT hr, expected_hr;
7728 unsigned int i, r;
7729 IDirect3D9 *d3d;
7730 ULONG refcount;
7731 HWND window;
7732 BYTE *base;
7733 static const struct
7735 D3DRESOURCETYPE type;
7736 D3DPOOL pool;
7737 const char *name;
7739 resources[] =
7741 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7742 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7743 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7744 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7745 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7746 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7747 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7750 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7751 0, 0, 640, 480, 0, 0, 0, 0);
7752 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7753 ok(!!d3d, "Failed to create a D3D object.\n");
7754 if (!(device = create_device(d3d, window, NULL)))
7756 skip("Failed to create a D3D device, skipping tests.\n");
7757 IDirect3D9_Release(d3d);
7758 DestroyWindow(window);
7759 return;
7762 for (r = 0; r < ARRAY_SIZE(resources); ++r)
7764 texture = NULL;
7765 cube_texture = NULL;
7766 switch (resources[r].type)
7768 case D3DRTYPE_SURFACE:
7769 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7770 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7771 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7772 hr, resources[r].name);
7773 break;
7775 case D3DRTYPE_TEXTURE:
7776 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7777 resources[r].pool, &texture, NULL);
7778 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7779 hr, resources[r].name);
7780 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7781 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7782 hr, resources[r].name);
7783 break;
7785 case D3DRTYPE_CUBETEXTURE:
7786 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7787 resources[r].pool, &cube_texture, NULL);
7788 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7789 hr, resources[r].name);
7790 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7791 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7792 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7793 hr, resources[r].name);
7794 break;
7796 default:
7797 break;
7800 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7801 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7802 base = locked_rect.pBits;
7803 hr = IDirect3DSurface9_UnlockRect(surface);
7804 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7805 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
7806 hr = IDirect3DSurface9_UnlockRect(surface);
7807 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
7809 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7811 unsigned int offset, expected_offset;
7812 const RECT *rect = &test_data[i].rect;
7814 locked_rect.pBits = (BYTE *)0xdeadbeef;
7815 locked_rect.Pitch = 0xdeadbeef;
7817 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7818 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7819 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7820 * one broken. */
7821 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7822 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7823 wine_dbgstr_rect(rect), hr, resources[r].name);
7824 if (FAILED(hr))
7825 continue;
7827 offset = (BYTE *)locked_rect.pBits - base;
7828 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7829 ok(offset == expected_offset,
7830 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7831 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7833 hr = IDirect3DSurface9_UnlockRect(surface);
7834 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7836 if (texture)
7838 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7839 ok(SUCCEEDED(hr),
7840 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7841 wine_dbgstr_rect(rect), hr, resources[r].name);
7842 if (FAILED(hr))
7843 continue;
7845 offset = (BYTE *)locked_rect.pBits - base;
7846 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7847 ok(offset == expected_offset,
7848 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7849 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7851 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7852 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7854 if (cube_texture)
7856 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7857 &locked_rect, rect, 0);
7858 ok(SUCCEEDED(hr),
7859 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7860 wine_dbgstr_rect(rect), hr, resources[r].name);
7861 if (FAILED(hr))
7862 continue;
7864 offset = (BYTE *)locked_rect.pBits - base;
7865 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7866 ok(offset == expected_offset,
7867 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7868 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7870 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7871 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7875 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7876 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7877 locked_rect.pBits = (BYTE *)0xdeadbeef;
7878 locked_rect.Pitch = 1;
7879 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7880 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7881 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7882 locked_rect.pBits, resources[r].name);
7883 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7884 locked_rect.Pitch, resources[r].name);
7885 hr = IDirect3DSurface9_UnlockRect(surface);
7886 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7888 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7889 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7890 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7891 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7892 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7893 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7894 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7895 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7896 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7897 hr = IDirect3DSurface9_UnlockRect(surface);
7898 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7900 IDirect3DSurface9_Release(surface);
7902 if (texture)
7904 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7905 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7906 hr, resources[r].name);
7907 locked_rect.pBits = (BYTE *)0xdeadbeef;
7908 locked_rect.Pitch = 1;
7909 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7910 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7911 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7912 locked_rect.pBits, resources[r].name);
7913 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7914 locked_rect.Pitch, resources[r].name);
7915 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7916 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7917 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7918 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7919 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7920 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7922 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7923 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7924 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7925 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7926 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7927 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7928 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7929 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7930 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7931 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7932 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7934 IDirect3DTexture9_Release(texture);
7936 if (cube_texture)
7938 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7939 &locked_rect, NULL, 0);
7940 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7941 hr, resources[r].name);
7942 locked_rect.pBits = (BYTE *)0xdeadbeef;
7943 locked_rect.Pitch = 1;
7944 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7945 &locked_rect, NULL, 0);
7946 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7947 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7948 locked_rect.pBits, resources[r].name);
7949 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7950 locked_rect.Pitch, resources[r].name);
7951 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7952 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7953 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7954 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7955 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7956 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7958 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7959 &locked_rect, &test_data[0].rect, 0);
7960 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7961 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7962 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7963 &locked_rect, &test_data[0].rect, 0);
7964 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7965 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7966 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7967 &locked_rect, &test_rect_2, 0);
7968 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7969 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7970 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7971 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7973 IDirect3DCubeTexture9_Release(cube_texture);
7977 refcount = IDirect3DDevice9_Release(device);
7978 ok(!refcount, "Device has %u references left.\n", refcount);
7979 IDirect3D9_Release(d3d);
7980 DestroyWindow(window);
7983 static void test_private_data(void)
7985 ULONG refcount, expected_refcount;
7986 IDirect3DTexture9 *texture;
7987 IDirect3DSurface9 *surface, *surface2;
7988 IDirect3DDevice9 *device;
7989 IDirect3D9 *d3d;
7990 IUnknown *ptr;
7991 HWND window;
7992 HRESULT hr;
7993 DWORD size;
7994 DWORD data[4] = {1, 2, 3, 4};
7995 static const GUID d3d9_private_data_test_guid2 =
7997 0x2e5afac2,
7998 0x87b5,
7999 0x4c10,
8000 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
8003 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8004 0, 0, 640, 480, 0, 0, 0, 0);
8005 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8006 ok(!!d3d, "Failed to create a D3D object.\n");
8007 if (!(device = create_device(d3d, window, NULL)))
8009 skip("Failed to create a D3D device, skipping tests.\n");
8010 IDirect3D9_Release(d3d);
8011 DestroyWindow(window);
8012 return;
8015 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
8016 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8017 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8019 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8020 device, 0, D3DSPD_IUNKNOWN);
8021 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8022 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8023 device, 5, D3DSPD_IUNKNOWN);
8024 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8025 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8026 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
8027 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8029 /* A failing SetPrivateData call does not clear the old data with the same tag. */
8030 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
8031 sizeof(device), D3DSPD_IUNKNOWN);
8032 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8033 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
8034 sizeof(device) * 2, D3DSPD_IUNKNOWN);
8035 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8036 size = sizeof(ptr);
8037 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8038 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8039 IUnknown_Release(ptr);
8040 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8041 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8043 refcount = get_refcount((IUnknown *)device);
8044 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8045 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8046 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8047 expected_refcount = refcount + 1;
8048 refcount = get_refcount((IUnknown *)device);
8049 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8050 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8051 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8052 expected_refcount = refcount - 1;
8053 refcount = get_refcount((IUnknown *)device);
8054 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8056 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8057 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8058 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8059 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8060 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8061 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8062 refcount = get_refcount((IUnknown *)device);
8063 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8065 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8066 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8067 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8068 size = 2 * sizeof(ptr);
8069 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8070 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8071 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8072 expected_refcount = refcount + 2;
8073 refcount = get_refcount((IUnknown *)device);
8074 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8075 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
8076 IUnknown_Release(ptr);
8077 expected_refcount--;
8079 ptr = (IUnknown *)0xdeadbeef;
8080 size = 1;
8081 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8082 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8083 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8084 size = 2 * sizeof(ptr);
8085 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8086 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8087 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8088 refcount = get_refcount((IUnknown *)device);
8089 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8090 size = 1;
8091 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8092 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8093 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8094 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8095 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
8096 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8097 size = 0xdeadbabe;
8098 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
8099 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8100 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8101 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
8102 /* GetPrivateData with size = NULL causes an access violation on Windows if the
8103 * requested data exists. */
8105 /* Destroying the surface frees the held reference. */
8106 IDirect3DSurface9_Release(surface);
8107 expected_refcount = refcount - 2;
8108 refcount = get_refcount((IUnknown *)device);
8109 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8111 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
8112 &texture, NULL);
8113 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8114 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8115 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
8116 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
8117 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
8119 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8120 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8122 memset(data, 0, sizeof(data));
8123 size = sizeof(data);
8124 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
8125 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8126 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
8127 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8128 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
8129 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
8131 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
8132 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8134 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8135 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8136 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
8137 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8139 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8140 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8142 IDirect3DSurface9_Release(surface2);
8143 IDirect3DSurface9_Release(surface);
8144 IDirect3DTexture9_Release(texture);
8146 refcount = IDirect3DDevice9_Release(device);
8147 ok(!refcount, "Device has %u references left.\n", refcount);
8148 IDirect3D9_Release(d3d);
8149 DestroyWindow(window);
8152 static void test_getdc(void)
8154 static const struct
8156 const char *name;
8157 D3DFORMAT format;
8158 unsigned int bit_count;
8159 DWORD mask_r, mask_g, mask_b;
8160 BOOL getdc_supported;
8162 testdata[] =
8164 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8165 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8166 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
8167 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8168 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8169 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
8170 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8171 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8172 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8173 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8174 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8175 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8176 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8177 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8178 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8179 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
8180 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8181 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8182 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8183 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8185 IDirect3DSurface9 *surface, *surface2;
8186 IDirect3DCubeTexture9 *cube_texture;
8187 struct device_desc device_desc;
8188 IDirect3DTexture9 *texture;
8189 IDirect3DDevice9 *device;
8190 D3DLOCKED_RECT map_desc;
8191 IDirect3D9 *d3d;
8192 unsigned int i;
8193 ULONG refcount;
8194 HWND window;
8195 HDC dc, dc2;
8196 HRESULT hr;
8198 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8199 0, 0, 640, 480, 0, 0, 0, 0);
8200 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8201 ok(!!d3d, "Failed to create a D3D object.\n");
8202 if (!(device = create_device(d3d, window, NULL)))
8204 skip("Failed to create a D3D device, skipping tests.\n");
8205 IDirect3D9_Release(d3d);
8206 DestroyWindow(window);
8207 return;
8210 for (i = 0; i < ARRAY_SIZE(testdata); ++i)
8212 texture = NULL;
8213 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8214 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
8215 if (FAILED(hr))
8217 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
8218 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
8219 if (FAILED(hr))
8221 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8222 continue;
8224 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8225 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8228 dc = (void *)0x1234;
8229 hr = IDirect3DSurface9_GetDC(surface, &dc);
8230 if (testdata[i].getdc_supported)
8231 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8232 else
8233 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8235 if (SUCCEEDED(hr))
8237 unsigned int width_bytes;
8238 DIBSECTION dib;
8239 HBITMAP bitmap;
8240 DWORD type;
8241 int size;
8243 type = GetObjectType(dc);
8244 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8245 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8246 type = GetObjectType(bitmap);
8247 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8249 size = GetObjectA(bitmap, sizeof(dib), &dib);
8250 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
8251 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
8252 dib.dsBm.bmType, testdata[i].name);
8253 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
8254 dib.dsBm.bmWidth, testdata[i].name);
8255 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
8256 dib.dsBm.bmHeight, testdata[i].name);
8257 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
8258 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
8259 dib.dsBm.bmWidthBytes, testdata[i].name);
8260 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
8261 dib.dsBm.bmPlanes, testdata[i].name);
8262 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
8263 "Got unexpected bit count %d for format %s.\n",
8264 dib.dsBm.bmBitsPixel, testdata[i].name);
8265 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
8266 dib.dsBm.bmBits, testdata[i].name);
8268 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
8269 dib.dsBmih.biSize, testdata[i].name);
8270 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
8271 dib.dsBmih.biHeight, testdata[i].name);
8272 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
8273 dib.dsBmih.biHeight, testdata[i].name);
8274 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
8275 dib.dsBmih.biPlanes, testdata[i].name);
8276 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
8277 dib.dsBmih.biBitCount, testdata[i].name);
8278 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
8279 "Got unexpected compression %#x for format %s.\n",
8280 dib.dsBmih.biCompression, testdata[i].name);
8281 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
8282 dib.dsBmih.biSizeImage, testdata[i].name);
8283 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
8284 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
8285 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
8286 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
8287 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
8288 dib.dsBmih.biClrUsed, testdata[i].name);
8289 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
8290 dib.dsBmih.biClrImportant, testdata[i].name);
8292 if (dib.dsBmih.biCompression == BI_BITFIELDS)
8294 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
8295 && dib.dsBitfields[2] == testdata[i].mask_b,
8296 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8297 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8299 else
8301 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
8302 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8303 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8305 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
8306 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
8308 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8309 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
8311 else
8313 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
8316 IDirect3DSurface9_Release(surface);
8317 if (texture)
8318 IDirect3DTexture9_Release(texture);
8320 if (!testdata[i].getdc_supported)
8321 continue;
8323 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
8324 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
8326 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8327 continue;
8330 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
8331 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8332 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
8333 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8335 hr = IDirect3DSurface9_GetDC(surface, &dc);
8336 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8337 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8338 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8339 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8340 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8341 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8342 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8344 hr = IDirect3DSurface9_GetDC(surface, &dc);
8345 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8346 dc2 = (void *)0x1234;
8347 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8348 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8349 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
8350 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8351 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8352 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8353 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8355 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8356 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8357 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8358 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8359 hr = IDirect3DSurface9_UnlockRect(surface);
8360 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8361 hr = IDirect3DSurface9_UnlockRect(surface);
8362 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8364 hr = IDirect3DSurface9_GetDC(surface, &dc);
8365 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8366 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8367 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8368 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8369 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8371 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8372 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8373 hr = IDirect3DSurface9_GetDC(surface, &dc);
8374 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8375 hr = IDirect3DSurface9_UnlockRect(surface);
8376 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8378 hr = IDirect3DSurface9_GetDC(surface, &dc);
8379 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8380 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
8381 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8382 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
8383 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8384 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8385 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8387 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8388 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8389 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8390 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8391 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
8392 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8393 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8394 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8396 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8397 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8398 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8399 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8400 hr = IDirect3DSurface9_UnlockRect(surface2);
8401 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8402 hr = IDirect3DSurface9_UnlockRect(surface);
8403 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8405 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8406 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8407 hr = IDirect3DSurface9_GetDC(surface, &dc);
8408 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8409 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8410 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8411 hr = IDirect3DSurface9_UnlockRect(surface);
8412 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8414 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8415 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8416 hr = IDirect3DSurface9_GetDC(surface, &dc);
8417 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8418 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8419 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8420 hr = IDirect3DSurface9_UnlockRect(surface2);
8421 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8423 hr = IDirect3DSurface9_GetDC(surface, &dc);
8424 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8425 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8426 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8427 hr = IDirect3DSurface9_UnlockRect(surface2);
8428 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8429 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8430 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8432 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8433 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8434 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8436 hr = IDirect3DSurface9_UnlockRect(surface);
8437 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8438 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8439 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8441 hr = IDirect3DSurface9_UnlockRect(surface);
8442 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8443 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8444 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8445 hr = IDirect3DSurface9_UnlockRect(surface);
8446 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8447 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8448 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8449 hr = IDirect3DSurface9_UnlockRect(surface);
8450 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8452 hr = IDirect3DSurface9_UnlockRect(surface2);
8453 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8454 hr = IDirect3DSurface9_GetDC(surface, &dc);
8455 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8456 hr = IDirect3DSurface9_UnlockRect(surface2);
8457 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8458 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8459 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8460 hr = IDirect3DSurface9_UnlockRect(surface2);
8461 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8463 IDirect3DSurface9_Release(surface2);
8464 IDirect3DSurface9_Release(surface);
8465 IDirect3DCubeTexture9_Release(cube_texture);
8468 refcount = IDirect3DDevice9_Release(device);
8469 ok(!refcount, "Device has %u references left.\n", refcount);
8471 /* Backbuffer created with D3DFMT_UNKNOWN format. */
8472 device_desc.width = 640;
8473 device_desc.height = 480;
8474 device_desc.device_window = window;
8475 device_desc.flags = CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT | CREATE_DEVICE_LOCKABLE_BACKBUFFER;
8477 device = create_device(d3d, window, &device_desc);
8478 ok(!!device, "Failed to create device.\n");
8480 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8481 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
8483 dc = NULL;
8484 hr = IDirect3DSurface9_GetDC(surface, &dc);
8485 ok(!!dc, "Unexpected DC returned.\n");
8486 ok(SUCCEEDED(hr), "Failed to get backbuffer DC, hr %#x.\n", hr);
8487 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8488 ok(SUCCEEDED(hr), "Failed to release backbuffer DC, hr %#x.\n", hr);
8490 IDirect3DSurface9_Release(surface);
8492 refcount = IDirect3DDevice9_Release(device);
8493 ok(!refcount, "Device has %u references left.\n", refcount);
8495 IDirect3D9_Release(d3d);
8496 DestroyWindow(window);
8499 static void test_surface_dimensions(void)
8501 IDirect3DSurface9 *surface;
8502 IDirect3DDevice9 *device;
8503 IDirect3D9 *d3d;
8504 ULONG refcount;
8505 HWND window;
8506 HRESULT hr;
8508 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8509 0, 0, 640, 480, 0, 0, 0, 0);
8510 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8511 ok(!!d3d, "Failed to create a D3D object.\n");
8512 if (!(device = create_device(d3d, window, NULL)))
8514 skip("Failed to create a D3D device, skipping tests.\n");
8515 IDirect3D9_Release(d3d);
8516 DestroyWindow(window);
8517 return;
8520 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8521 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8522 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8523 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8524 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8525 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8527 refcount = IDirect3DDevice9_Release(device);
8528 ok(!refcount, "Device has %u references left.\n", refcount);
8529 IDirect3D9_Release(d3d);
8530 DestroyWindow(window);
8533 static void test_surface_format_null(void)
8535 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8536 IDirect3DTexture9 *texture;
8537 IDirect3DSurface9 *surface;
8538 IDirect3DSurface9 *rt, *ds;
8539 D3DLOCKED_RECT locked_rect;
8540 IDirect3DDevice9 *device;
8541 D3DSURFACE_DESC desc;
8542 IDirect3D9 *d3d;
8543 ULONG refcount;
8544 HWND window;
8545 HRESULT hr;
8547 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8548 ok(!!d3d, "Failed to create a D3D object.\n");
8550 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8551 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8552 if (hr != D3D_OK)
8554 skip("No D3DFMT_NULL support, skipping test.\n");
8555 IDirect3D9_Release(d3d);
8556 return;
8559 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8560 0, 0, 640, 480, 0, 0, 0, 0);
8561 if (!(device = create_device(d3d, window, NULL)))
8563 skip("Failed to create a D3D device, skipping tests.\n");
8564 IDirect3D9_Release(d3d);
8565 DestroyWindow(window);
8566 return;
8569 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8570 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8571 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8573 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8574 D3DFMT_NULL, D3DFMT_D24S8);
8575 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8577 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8578 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8579 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8581 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8582 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8584 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8585 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8587 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8588 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8590 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8591 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8593 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8594 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8596 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8597 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8599 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8600 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8602 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8603 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8605 IDirect3DSurface9_Release(rt);
8606 IDirect3DSurface9_Release(ds);
8608 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8609 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8610 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8611 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8613 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8614 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8615 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8616 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8618 hr = IDirect3DSurface9_UnlockRect(surface);
8619 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8621 IDirect3DSurface9_Release(surface);
8623 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8624 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8625 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8626 IDirect3DTexture9_Release(texture);
8628 refcount = IDirect3DDevice9_Release(device);
8629 ok(!refcount, "Device has %u references left.\n", refcount);
8630 IDirect3D9_Release(d3d);
8631 DestroyWindow(window);
8634 static void test_surface_double_unlock(void)
8636 static const D3DPOOL pools[] =
8638 D3DPOOL_DEFAULT,
8639 D3DPOOL_SCRATCH,
8640 D3DPOOL_SYSTEMMEM,
8642 IDirect3DSurface9 *surface;
8643 IDirect3DDevice9 *device;
8644 D3DLOCKED_RECT lr;
8645 IDirect3D9 *d3d;
8646 unsigned int i;
8647 ULONG refcount;
8648 HWND window;
8649 HRESULT hr;
8651 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8652 0, 0, 640, 480, 0, 0, 0, 0);
8653 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8654 ok(!!d3d, "Failed to create a D3D object.\n");
8655 if (!(device = create_device(d3d, window, NULL)))
8657 skip("Failed to create a D3D device, skipping tests.\n");
8658 IDirect3D9_Release(d3d);
8659 DestroyWindow(window);
8660 return;
8663 for (i = 0; i < ARRAY_SIZE(pools); ++i)
8665 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8666 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8667 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8669 hr = IDirect3DSurface9_UnlockRect(surface);
8670 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8671 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8672 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8673 hr = IDirect3DSurface9_UnlockRect(surface);
8674 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8675 hr = IDirect3DSurface9_UnlockRect(surface);
8676 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8678 IDirect3DSurface9_Release(surface);
8681 refcount = IDirect3DDevice9_Release(device);
8682 ok(!refcount, "Device has %u references left.\n", refcount);
8683 IDirect3D9_Release(d3d);
8684 DestroyWindow(window);
8687 static void test_surface_blocks(void)
8689 static const struct
8691 D3DFORMAT fmt;
8692 const char *name;
8693 unsigned int block_width;
8694 unsigned int block_height;
8695 BOOL broken;
8696 BOOL create_size_checked, core_fmt;
8698 formats[] =
8700 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8701 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8702 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8703 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8704 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8705 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8706 * which doesn't match the format spec. On newer Nvidia cards
8707 * they have the correct 4x4 block size */
8708 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8709 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8710 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8711 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8713 static const struct
8715 D3DPOOL pool;
8716 const char *name;
8717 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8718 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8719 BOOL success;
8721 pools[] =
8723 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8724 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8725 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8726 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8728 static struct
8730 D3DRESOURCETYPE rtype;
8731 const char *type_name;
8732 D3DPOOL pool;
8733 const char *pool_name;
8734 BOOL need_driver_support, need_runtime_support;
8736 create_tests[] =
8738 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8739 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8740 /* Managed offscreen plain surfaces are not supported */
8741 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8743 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8744 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8745 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8746 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8748 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8749 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8750 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8751 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8753 IDirect3DTexture9 *texture;
8754 IDirect3DCubeTexture9 *cube_texture;
8755 IDirect3DSurface9 *surface;
8756 D3DLOCKED_RECT locked_rect;
8757 IDirect3DDevice9 *device;
8758 unsigned int i, j, k, w, h;
8759 BOOL surface_only;
8760 IDirect3D9 *d3d;
8761 ULONG refcount;
8762 HWND window;
8763 HRESULT hr;
8764 RECT rect;
8765 BOOL tex_pow2, cube_pow2;
8766 D3DCAPS9 caps;
8767 static const RECT invalid[] =
8769 {60, 60, 60, 68}, /* 0 height */
8770 {60, 60, 68, 60}, /* 0 width */
8771 {68, 60, 60, 68}, /* left > right */
8772 {60, 68, 68, 60}, /* top > bottom */
8773 {-8, 60, 0, 68}, /* left < surface */
8774 {60, -8, 68, 0}, /* top < surface */
8775 {-16, 60, -8, 68}, /* right < surface */
8776 {60, -16, 68, -8}, /* bottom < surface */
8777 {60, 60, 136, 68}, /* right > surface */
8778 {60, 60, 68, 136}, /* bottom > surface */
8779 {136, 60, 144, 68}, /* left > surface */
8780 {60, 136, 68, 144}, /* top > surface */
8783 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8784 0, 0, 640, 480, 0, 0, 0, 0);
8785 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8786 ok(!!d3d, "Failed to create a D3D object.\n");
8787 if (!(device = create_device(d3d, window, NULL)))
8789 skip("Failed to create a D3D device, skipping tests.\n");
8790 IDirect3D9_Release(d3d);
8791 DestroyWindow(window);
8792 return;
8795 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8796 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8797 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8798 if (tex_pow2)
8799 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8800 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8802 for (i = 0; i < ARRAY_SIZE(formats); ++i)
8804 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8806 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8807 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8808 tex_support = SUCCEEDED(hr);
8809 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8810 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8811 cube_support = SUCCEEDED(hr);
8812 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8813 0, D3DRTYPE_SURFACE, formats[i].fmt);
8814 surface_support = SUCCEEDED(hr);
8816 /* Scratch pool in general allows texture creation even if the driver does
8817 * not support the format. If the format is an extension format that is not
8818 * known to the runtime, like ATI2N, some driver support is required for
8819 * this to work.
8821 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8822 * about ATI2N. I cannot check this because all my Vista+ machines support
8823 * ATI2N in hardware, but none of my WinXP machines do. */
8824 format_known = tex_support || cube_support || surface_support;
8826 for (w = 1; w <= 8; w++)
8828 for (h = 1; h <= 8; h++)
8830 BOOL block_aligned = TRUE;
8831 BOOL size_is_pow2;
8833 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8834 block_aligned = FALSE;
8836 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8838 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
8840 BOOL support, pow2;
8841 HRESULT expect_hr;
8842 BOOL may_succeed = FALSE;
8843 IUnknown **check_null;
8845 if (!formats[i].core_fmt)
8847 /* AMD warns against creating ATI2N textures smaller than
8848 * the block size because the runtime cannot calculate the
8849 * correct texture size. Generalize this for all extension
8850 * formats. */
8851 if (w < formats[i].block_width || h < formats[i].block_height)
8852 continue;
8855 texture = (IDirect3DTexture9 *)0xdeadbeef;
8856 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8857 surface = (IDirect3DSurface9 *)0xdeadbeef;
8859 switch (create_tests[j].rtype)
8861 case D3DRTYPE_TEXTURE:
8862 check_null = (IUnknown **)&texture;
8863 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8864 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8865 support = tex_support;
8866 pow2 = tex_pow2;
8867 break;
8869 case D3DRTYPE_CUBETEXTURE:
8870 if (w != h)
8871 continue;
8872 check_null = (IUnknown **)&cube_texture;
8873 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8874 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8875 support = cube_support;
8876 pow2 = cube_pow2;
8877 break;
8879 case D3DRTYPE_SURFACE:
8880 check_null = (IUnknown **)&surface;
8881 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8882 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8883 support = surface_support;
8884 pow2 = FALSE;
8885 break;
8887 default:
8888 check_null = NULL;
8889 pow2 = FALSE;
8890 support = FALSE;
8891 break;
8894 if (create_tests[j].need_driver_support && !support)
8895 expect_hr = D3DERR_INVALIDCALL;
8896 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8897 expect_hr = D3DERR_INVALIDCALL;
8898 else if (formats[i].create_size_checked && !block_aligned)
8899 expect_hr = D3DERR_INVALIDCALL;
8900 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8901 expect_hr = D3DERR_INVALIDCALL;
8902 else
8903 expect_hr = D3D_OK;
8905 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8906 * does not support it. Accept scratch creation of extension formats on
8907 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8908 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8909 * support it. */
8910 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8911 may_succeed = TRUE;
8913 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8914 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8915 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8916 if (FAILED(hr))
8917 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8918 else
8919 IUnknown_Release(*check_null);
8924 surface_only = FALSE;
8925 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8926 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8927 dynamic_tex_support = SUCCEEDED(hr);
8928 if (!dynamic_tex_support)
8930 if (!surface_support)
8932 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8933 continue;
8935 surface_only = TRUE;
8938 for (j = 0; j < ARRAY_SIZE(pools); ++j)
8940 switch (pools[j].pool)
8942 case D3DPOOL_SYSTEMMEM:
8943 case D3DPOOL_MANAGED:
8944 if (surface_only)
8945 continue;
8946 /* Fall through */
8947 case D3DPOOL_DEFAULT:
8948 if (surface_only)
8950 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8951 formats[i].fmt, pools[j].pool, &surface, NULL);
8952 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8954 else
8956 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8957 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8958 formats[i].fmt, pools[j].pool, &texture, NULL);
8959 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8960 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8961 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8962 IDirect3DTexture9_Release(texture);
8964 break;
8966 case D3DPOOL_SCRATCH:
8967 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8968 formats[i].fmt, pools[j].pool, &surface, NULL);
8969 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8970 break;
8972 default:
8973 break;
8976 if (formats[i].block_width > 1)
8978 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8979 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8980 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8981 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8982 SUCCEEDED(hr) ? "succeeded" : "failed",
8983 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8984 if (SUCCEEDED(hr))
8986 hr = IDirect3DSurface9_UnlockRect(surface);
8987 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8990 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8991 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8992 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8993 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8994 SUCCEEDED(hr) ? "succeeded" : "failed",
8995 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8996 if (SUCCEEDED(hr))
8998 hr = IDirect3DSurface9_UnlockRect(surface);
8999 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9003 if (formats[i].block_height > 1)
9005 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
9006 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9007 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9008 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9009 SUCCEEDED(hr) ? "succeeded" : "failed",
9010 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9011 if (SUCCEEDED(hr))
9013 hr = IDirect3DSurface9_UnlockRect(surface);
9014 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9017 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
9018 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9019 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9020 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9021 SUCCEEDED(hr) ? "succeeded" : "failed",
9022 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9023 if (SUCCEEDED(hr))
9025 hr = IDirect3DSurface9_UnlockRect(surface);
9026 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9030 for (k = 0; k < ARRAY_SIZE(invalid); ++k)
9032 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
9033 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
9034 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
9035 formats[i].name, pools[j].name, k);
9036 if (SUCCEEDED(hr))
9038 hr = IDirect3DSurface9_UnlockRect(surface);
9039 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9043 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
9044 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9045 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
9046 hr = IDirect3DSurface9_UnlockRect(surface);
9047 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9049 IDirect3DSurface9_Release(surface);
9052 if (!dynamic_tex_support)
9054 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
9055 continue;
9058 if (formats[i].block_width == 1 && formats[i].block_height == 1)
9059 continue;
9060 if (!formats[i].core_fmt)
9061 continue;
9063 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
9064 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
9065 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
9067 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
9068 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9069 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9070 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9072 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
9073 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
9074 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9075 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9076 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9077 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9079 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
9080 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9081 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9082 if (SUCCEEDED(hr))
9083 IDirect3DTexture9_UnlockRect(texture, 1);
9085 IDirect3DTexture9_Release(texture);
9088 refcount = IDirect3DDevice9_Release(device);
9089 ok(!refcount, "Device has %u references left.\n", refcount);
9090 IDirect3D9_Release(d3d);
9091 DestroyWindow(window);
9094 static void test_set_palette(void)
9096 IDirect3DDevice9 *device;
9097 IDirect3D9 *d3d9;
9098 UINT refcount;
9099 HWND window;
9100 HRESULT hr;
9101 PALETTEENTRY pal[256];
9102 unsigned int i;
9103 D3DCAPS9 caps;
9105 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9106 0, 0, 640, 480, 0, 0, 0, 0);
9107 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9108 ok(!!d3d9, "Failed to create a D3D object.\n");
9109 if (!(device = create_device(d3d9, window, NULL)))
9111 skip("Failed to create a D3D device, skipping tests.\n");
9112 DestroyWindow(window);
9113 return;
9116 for (i = 0; i < ARRAY_SIZE(pal); i++)
9118 pal[i].peRed = i;
9119 pal[i].peGreen = i;
9120 pal[i].peBlue = i;
9121 pal[i].peFlags = 0xff;
9123 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9124 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9126 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9127 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9128 for (i = 0; i < ARRAY_SIZE(pal); i++)
9130 pal[i].peRed = i;
9131 pal[i].peGreen = i;
9132 pal[i].peBlue = i;
9133 pal[i].peFlags = i;
9135 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
9137 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9138 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9140 else
9142 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9143 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
9146 refcount = IDirect3DDevice9_Release(device);
9147 ok(!refcount, "Device has %u references left.\n", refcount);
9148 IDirect3D9_Release(d3d9);
9149 DestroyWindow(window);
9152 static void test_swvp_buffer(void)
9154 IDirect3DDevice9 *device;
9155 IDirect3D9 *d3d9;
9156 UINT refcount;
9157 HWND window;
9158 HRESULT hr;
9159 unsigned int i;
9160 IDirect3DVertexBuffer9 *buffer;
9161 static const unsigned int bufsize = 1024;
9162 D3DVERTEXBUFFER_DESC desc;
9163 struct device_desc device_desc;
9164 struct
9166 float x, y, z;
9167 } *ptr, *ptr2;
9169 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9170 0, 0, 640, 480, 0, 0, 0, 0);
9171 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9172 ok(!!d3d9, "Failed to create a D3D object.\n");
9174 device_desc.device_window = window;
9175 device_desc.width = 640;
9176 device_desc.height = 480;
9177 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
9178 if (!(device = create_device(d3d9, window, &device_desc)))
9180 skip("Failed to create a D3D device, skipping tests.\n");
9181 DestroyWindow(window);
9182 IDirect3D9_Release(d3d9);
9183 return;
9186 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
9187 D3DPOOL_DEFAULT, &buffer, NULL);
9188 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9189 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9190 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9191 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
9192 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
9193 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
9195 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9196 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9197 for (i = 0; i < bufsize; i++)
9199 ptr[i].x = i * 1.0f;
9200 ptr[i].y = i * 2.0f;
9201 ptr[i].z = i * 3.0f;
9203 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9204 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9206 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9207 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9208 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9209 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9210 hr = IDirect3DDevice9_BeginScene(device);
9211 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9212 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9213 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9214 hr = IDirect3DDevice9_EndScene(device);
9215 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9217 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9218 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9219 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
9220 for (i = 0; i < bufsize; i++)
9222 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9224 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
9225 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9226 break;
9229 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9230 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9232 IDirect3DVertexBuffer9_Release(buffer);
9233 refcount = IDirect3DDevice9_Release(device);
9234 ok(!refcount, "Device has %u references left.\n", refcount);
9235 IDirect3D9_Release(d3d9);
9236 DestroyWindow(window);
9239 static void test_managed_buffer(void)
9241 static const unsigned int vertex_count = 1024;
9242 IDirect3DVertexBuffer9 *buffer;
9243 D3DVERTEXBUFFER_DESC desc;
9244 IDirect3DDevice9 *device;
9245 struct vec3 *ptr, *ptr2;
9246 IDirect3D9 *d3d9;
9247 unsigned int i;
9248 UINT refcount;
9249 HWND window;
9250 HRESULT hr;
9252 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9253 0, 0, 640, 480, 0, 0, 0, 0);
9254 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9255 ok(!!d3d9, "Failed to create a D3D object.\n");
9256 if (!(device = create_device(d3d9, window, NULL)))
9258 skip("Failed to create a D3D device, skipping tests.\n");
9259 IDirect3D9_Release(d3d9);
9260 DestroyWindow(window);
9261 return;
9264 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
9265 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
9266 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9267 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9268 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9269 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
9270 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
9272 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9273 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9274 for (i = 0; i < vertex_count; ++i)
9276 ptr[i].x = i * 1.0f;
9277 ptr[i].y = i * 2.0f;
9278 ptr[i].z = i * 3.0f;
9280 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9281 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9283 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9284 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9285 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9286 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9287 hr = IDirect3DDevice9_BeginScene(device);
9288 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9289 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9290 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9291 hr = IDirect3DDevice9_EndScene(device);
9292 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9294 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9295 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9296 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
9297 for (i = 0; i < vertex_count; ++i)
9299 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9301 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
9302 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9303 break;
9306 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9307 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9309 IDirect3DVertexBuffer9_Release(buffer);
9310 refcount = IDirect3DDevice9_Release(device);
9311 ok(!refcount, "Device has %u references left.\n", refcount);
9312 IDirect3D9_Release(d3d9);
9313 DestroyWindow(window);
9316 static void test_npot_textures(void)
9318 IDirect3DDevice9 *device = NULL;
9319 IDirect3D9 *d3d9;
9320 ULONG refcount;
9321 HWND window = NULL;
9322 HRESULT hr;
9323 D3DCAPS9 caps;
9324 IDirect3DTexture9 *texture;
9325 IDirect3DCubeTexture9 *cube_texture;
9326 IDirect3DVolumeTexture9 *volume_texture;
9327 struct
9329 D3DPOOL pool;
9330 const char *pool_name;
9331 HRESULT hr;
9333 pools[] =
9335 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
9336 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
9337 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
9338 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
9340 unsigned int i, levels;
9341 BOOL tex_pow2, cube_pow2, vol_pow2;
9343 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9344 0, 0, 640, 480, 0, 0, 0, 0);
9345 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9346 ok(!!d3d9, "Failed to create a D3D object.\n");
9347 if (!(device = create_device(d3d9, window, NULL)))
9349 skip("Failed to create a D3D device, skipping tests.\n");
9350 goto done;
9353 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9354 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9355 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
9356 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
9357 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9358 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
9359 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
9361 for (i = 0; i < ARRAY_SIZE(pools); i++)
9363 for (levels = 0; levels <= 2; levels++)
9365 HRESULT expected;
9367 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
9368 pools[i].pool, &texture, NULL);
9369 if (!tex_pow2)
9371 expected = D3D_OK;
9373 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
9375 if (levels == 1)
9376 expected = D3D_OK;
9377 else
9378 expected = pools[i].hr;
9380 else
9382 expected = pools[i].hr;
9384 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
9385 pools[i].pool_name, levels, hr, expected);
9387 if (SUCCEEDED(hr))
9388 IDirect3DTexture9_Release(texture);
9391 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9392 &cube_texture, NULL);
9393 if (tex_pow2)
9395 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9396 pools[i].pool_name, hr, pools[i].hr);
9398 else
9400 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9401 pools[i].pool_name, hr, D3D_OK);
9404 if (SUCCEEDED(hr))
9405 IDirect3DCubeTexture9_Release(cube_texture);
9407 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9408 &volume_texture, NULL);
9409 if (tex_pow2)
9411 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9412 pools[i].pool_name, hr, pools[i].hr);
9414 else
9416 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9417 pools[i].pool_name, hr, D3D_OK);
9420 if (SUCCEEDED(hr))
9421 IDirect3DVolumeTexture9_Release(volume_texture);
9424 done:
9425 if (device)
9427 refcount = IDirect3DDevice9_Release(device);
9428 ok(!refcount, "Device has %u references left.\n", refcount);
9430 IDirect3D9_Release(d3d9);
9431 DestroyWindow(window);
9435 static void test_vidmem_accounting(void)
9437 IDirect3DDevice9 *device;
9438 IDirect3D9 *d3d9;
9439 ULONG refcount;
9440 HWND window;
9441 HRESULT hr = D3D_OK;
9442 IDirect3DTexture9 *textures[20];
9443 unsigned int i;
9444 UINT vidmem_start, vidmem_end, diff;
9446 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9447 0, 0, 640, 480, 0, 0, 0, 0);
9448 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9449 ok(!!d3d9, "Failed to create a D3D object.\n");
9450 if (!(device = create_device(d3d9, window, NULL)))
9452 skip("Failed to create a D3D device, skipping tests.\n");
9453 IDirect3D9_Release(d3d9);
9454 DestroyWindow(window);
9455 return;
9458 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
9459 memset(textures, 0, sizeof(textures));
9460 for (i = 0; i < ARRAY_SIZE(textures); i++)
9462 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9463 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9464 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9465 * E_FAIL is returned on address space or system memory exhaustion */
9466 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9467 "Failed to create texture, hr %#x.\n", hr);
9469 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9471 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9472 diff = vidmem_start - vidmem_end;
9473 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9474 2 * i, diff / 1024 / 1024);
9476 for (i = 0; i < ARRAY_SIZE(textures); i++)
9478 if (textures[i])
9479 IDirect3DTexture9_Release(textures[i]);
9482 refcount = IDirect3DDevice9_Release(device);
9483 ok(!refcount, "Device has %u references left.\n", refcount);
9484 IDirect3D9_Release(d3d9);
9485 DestroyWindow(window);
9488 static void test_volume_locking(void)
9490 IDirect3DDevice9 *device;
9491 IDirect3D9 *d3d9;
9492 HWND window;
9493 HRESULT hr;
9494 IDirect3DVolumeTexture9 *texture;
9495 unsigned int i;
9496 D3DLOCKED_BOX locked_box;
9497 ULONG refcount;
9498 D3DCAPS9 caps;
9499 static const struct
9501 D3DPOOL pool;
9502 DWORD usage;
9503 HRESULT create_hr, lock_hr;
9505 tests[] =
9507 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9508 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9509 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9510 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9511 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9512 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9513 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9514 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9517 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9518 0, 0, 640, 480, 0, 0, 0, 0);
9519 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9520 ok(!!d3d9, "Failed to create a D3D object.\n");
9521 if (!(device = create_device(d3d9, window, NULL)))
9523 skip("Failed to create a D3D device, skipping tests.\n");
9524 IDirect3D9_Release(d3d9);
9525 DestroyWindow(window);
9526 return;
9529 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9530 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9531 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9533 skip("Volume textures not supported, skipping test.\n");
9534 goto out;
9537 for (i = 0; i < ARRAY_SIZE(tests); i++)
9539 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9540 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9541 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9542 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9543 if (FAILED(hr))
9544 continue;
9546 locked_box.pBits = (void *)0xdeadbeef;
9547 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9548 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9549 if (SUCCEEDED(hr))
9551 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9552 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9554 else
9556 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9558 IDirect3DVolumeTexture9_Release(texture);
9561 out:
9562 refcount = IDirect3DDevice9_Release(device);
9563 ok(!refcount, "Device has %u references left.\n", refcount);
9564 IDirect3D9_Release(d3d9);
9565 DestroyWindow(window);
9568 static void test_update_volumetexture(void)
9570 IDirect3DDevice9 *device;
9571 IDirect3D9 *d3d9;
9572 HWND window;
9573 HRESULT hr;
9574 IDirect3DVolumeTexture9 *src, *dst;
9575 unsigned int i;
9576 D3DLOCKED_BOX locked_box;
9577 ULONG refcount;
9578 D3DCAPS9 caps;
9579 static const struct
9581 D3DPOOL src_pool, dst_pool;
9582 HRESULT hr;
9584 tests[] =
9586 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9587 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9588 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9589 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9591 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9592 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9593 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9594 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9596 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9597 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9598 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9599 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9601 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9602 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9603 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9604 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9606 static const struct
9608 UINT src_size, dst_size;
9609 UINT src_lvl, dst_lvl;
9610 D3DFORMAT src_fmt, dst_fmt;
9612 tests2[] =
9614 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9615 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9616 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9617 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9618 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9619 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9620 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9621 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9624 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9625 0, 0, 640, 480, 0, 0, 0, 0);
9626 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9627 ok(!!d3d9, "Failed to create a D3D object.\n");
9628 if (!(device = create_device(d3d9, window, NULL)))
9630 skip("Failed to create a D3D device, skipping tests.\n");
9631 IDirect3D9_Release(d3d9);
9632 DestroyWindow(window);
9633 return;
9636 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9637 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9638 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9640 skip("Volume textures not supported, skipping test.\n");
9641 goto out;
9644 for (i = 0; i < ARRAY_SIZE(tests); i++)
9646 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9647 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9649 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9650 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9651 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9652 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9653 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9654 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9656 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9657 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9658 *((DWORD *)locked_box.pBits) = 0x11223344;
9659 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9660 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9662 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9663 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9664 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9666 if (SUCCEEDED(hr))
9668 DWORD content = *((DWORD *)locked_box.pBits);
9669 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9670 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9671 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9672 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9673 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9675 IDirect3DVolumeTexture9_Release(src);
9676 IDirect3DVolumeTexture9_Release(dst);
9679 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9681 skip("Mipmapped volume maps not supported.\n");
9682 goto out;
9685 for (i = 0; i < ARRAY_SIZE(tests2); i++)
9687 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9688 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9689 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9690 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9691 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9692 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9693 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9694 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9696 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9697 todo_wine_if (FAILED(hr))
9698 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9700 IDirect3DVolumeTexture9_Release(src);
9701 IDirect3DVolumeTexture9_Release(dst);
9704 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9705 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9706 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9707 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9708 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9710 * I'm not adding tests for this behavior until an application needs it. */
9712 out:
9713 refcount = IDirect3DDevice9_Release(device);
9714 ok(!refcount, "Device has %u references left.\n", refcount);
9715 IDirect3D9_Release(d3d9);
9716 DestroyWindow(window);
9719 static void test_create_rt_ds_fail(void)
9721 IDirect3DDevice9 *device;
9722 HWND window;
9723 HRESULT hr;
9724 ULONG refcount;
9725 IDirect3D9 *d3d9;
9726 IDirect3DSurface9 *surface;
9728 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9729 0, 0, 640, 480, 0, 0, 0, 0);
9730 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9731 ok(!!d3d9, "Failed to create a D3D object.\n");
9732 if (!(device = create_device(d3d9, window, NULL)))
9734 skip("Failed to create a D3D device, skipping tests.\n");
9735 IDirect3D9_Release(d3d9);
9736 DestroyWindow(window);
9737 return;
9740 /* Output pointer == NULL segfaults on Windows. */
9742 surface = (IDirect3DSurface9 *)0xdeadbeef;
9743 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9744 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9745 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9746 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9747 if (SUCCEEDED(hr))
9748 IDirect3DSurface9_Release(surface);
9750 surface = (IDirect3DSurface9 *)0xdeadbeef;
9751 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9752 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9753 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9754 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9755 if (SUCCEEDED(hr))
9756 IDirect3DSurface9_Release(surface);
9758 refcount = IDirect3DDevice9_Release(device);
9759 ok(!refcount, "Device has %u references left.\n", refcount);
9760 IDirect3D9_Release(d3d9);
9761 DestroyWindow(window);
9764 static void test_volume_blocks(void)
9766 IDirect3DDevice9 *device;
9767 IDirect3D9 *d3d9;
9768 UINT refcount;
9769 HWND window;
9770 HRESULT hr;
9771 D3DCAPS9 caps;
9772 IDirect3DVolumeTexture9 *texture;
9773 unsigned int w, h, d, i, j;
9774 static const struct
9776 D3DFORMAT fmt;
9777 const char *name;
9778 unsigned int block_width;
9779 unsigned int block_height;
9780 unsigned int block_depth;
9781 unsigned int block_size;
9782 unsigned int broken;
9783 BOOL create_size_checked, core_fmt;
9785 formats[] =
9787 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9788 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9789 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9790 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9791 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9792 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9793 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9794 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9795 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9796 * which doesn't match the format spec. On newer Nvidia cards
9797 * it has the correct 4x4 block size.
9798 * ATI1N volume textures are only supported by AMD GPUs right
9799 * now and locking offsets seem just wrong. */
9800 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9801 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9802 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9803 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9805 static const struct
9807 D3DPOOL pool;
9808 const char *name;
9809 BOOL need_driver_support, need_runtime_support;
9811 create_tests[] =
9813 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9814 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9815 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9816 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9818 static const struct
9820 unsigned int x, y, z, x2, y2, z2;
9822 offset_tests[] =
9824 {0, 0, 0, 8, 8, 8},
9825 {0, 0, 3, 8, 8, 8},
9826 {0, 4, 0, 8, 8, 8},
9827 {0, 4, 3, 8, 8, 8},
9828 {4, 0, 0, 8, 8, 8},
9829 {4, 0, 3, 8, 8, 8},
9830 {4, 4, 0, 8, 8, 8},
9831 {4, 4, 3, 8, 8, 8},
9833 D3DBOX box;
9834 D3DLOCKED_BOX locked_box;
9835 BYTE *base;
9836 INT expected_row_pitch, expected_slice_pitch;
9837 BOOL support;
9838 BOOL pow2;
9839 unsigned int offset, expected_offset;
9841 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9842 0, 0, 640, 480, 0, 0, 0, 0);
9843 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9844 ok(!!d3d9, "Failed to create a D3D object.\n");
9845 if (!(device = create_device(d3d9, window, NULL)))
9847 skip("Failed to create a D3D device, skipping tests.\n");
9848 IDirect3D9_Release(d3d9);
9849 DestroyWindow(window);
9850 return;
9852 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9853 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9854 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9856 for (i = 0; i < ARRAY_SIZE(formats); i++)
9858 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9859 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9860 support = SUCCEEDED(hr);
9862 /* Test creation restrictions */
9863 for (w = 1; w <= 8; w++)
9865 for (h = 1; h <= 8; h++)
9867 for (d = 1; d <= 8; d++)
9869 HRESULT expect_hr;
9870 BOOL size_is_pow2;
9871 BOOL block_aligned = TRUE;
9873 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9874 block_aligned = FALSE;
9876 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9878 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
9880 BOOL may_succeed = FALSE;
9882 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9883 expect_hr = D3DERR_INVALIDCALL;
9884 else if (formats[i].create_size_checked && !block_aligned)
9885 expect_hr = D3DERR_INVALIDCALL;
9886 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9887 expect_hr = D3DERR_INVALIDCALL;
9888 else if (create_tests[j].need_driver_support && !support)
9889 expect_hr = D3DERR_INVALIDCALL;
9890 else
9891 expect_hr = D3D_OK;
9893 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9894 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9895 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9897 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9898 * does not support it. Accept scratch creation of extension formats on
9899 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9900 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9901 * support it. */
9902 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9903 may_succeed = TRUE;
9905 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9906 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9907 hr, formats[i].name, create_tests[j].name, w, h, d);
9909 if (FAILED(hr))
9910 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9911 else
9912 IDirect3DVolumeTexture9_Release(texture);
9918 if (!support && !formats[i].core_fmt)
9919 continue;
9921 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9922 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9923 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9925 /* Test lockrect offset */
9926 for (j = 0; j < ARRAY_SIZE(offset_tests); j++)
9928 unsigned int bytes_per_pixel;
9929 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9931 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9932 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9934 base = locked_box.pBits;
9935 if (formats[i].broken == 1)
9937 expected_row_pitch = bytes_per_pixel * 24;
9939 else if (formats[i].broken == 2)
9941 expected_row_pitch = 24;
9943 else
9945 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9946 * formats[i].block_size;
9948 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9949 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9951 if (formats[i].broken)
9953 expected_slice_pitch = expected_row_pitch * 8;
9955 else
9957 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9958 * expected_row_pitch;
9960 ok(locked_box.SlicePitch == expected_slice_pitch,
9961 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9962 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9964 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9965 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9967 box.Left = offset_tests[j].x;
9968 box.Top = offset_tests[j].y;
9969 box.Front = offset_tests[j].z;
9970 box.Right = offset_tests[j].x2;
9971 box.Bottom = offset_tests[j].y2;
9972 box.Back = offset_tests[j].z2;
9973 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9974 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9976 offset = (BYTE *)locked_box.pBits - base;
9977 if (formats[i].broken == 1)
9979 expected_offset = box.Front * expected_slice_pitch
9980 + box.Top * expected_row_pitch
9981 + box.Left * bytes_per_pixel;
9983 else if (formats[i].broken == 2)
9985 expected_offset = box.Front * expected_slice_pitch
9986 + box.Top * expected_row_pitch
9987 + box.Left;
9989 else
9991 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9992 + (box.Top / formats[i].block_height) * expected_row_pitch
9993 + (box.Left / formats[i].block_width) * formats[i].block_size;
9995 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9996 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9998 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9999 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10002 /* Test partial block locks */
10003 box.Front = 0;
10004 box.Back = 1;
10005 if (formats[i].block_width > 1)
10007 box.Left = formats[i].block_width >> 1;
10008 box.Top = 0;
10009 box.Right = formats[i].block_width;
10010 box.Bottom = formats[i].block_height;
10011 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10012 ok(FAILED(hr) || broken(formats[i].broken),
10013 "Partial block lock succeeded, expected failure, format %s.\n",
10014 formats[i].name);
10015 if (SUCCEEDED(hr))
10017 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10018 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10021 box.Left = 0;
10022 box.Top = 0;
10023 box.Right = formats[i].block_width >> 1;
10024 box.Bottom = formats[i].block_height;
10025 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10026 ok(FAILED(hr) || broken(formats[i].broken),
10027 "Partial block lock succeeded, expected failure, format %s.\n",
10028 formats[i].name);
10029 if (SUCCEEDED(hr))
10031 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10032 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10036 if (formats[i].block_height > 1)
10038 box.Left = 0;
10039 box.Top = formats[i].block_height >> 1;
10040 box.Right = formats[i].block_width;
10041 box.Bottom = formats[i].block_height;
10042 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10043 ok(FAILED(hr) || broken(formats[i].broken),
10044 "Partial block lock succeeded, expected failure, format %s.\n",
10045 formats[i].name);
10046 if (SUCCEEDED(hr))
10048 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10049 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10052 box.Left = 0;
10053 box.Top = 0;
10054 box.Right = formats[i].block_width;
10055 box.Bottom = formats[i].block_height >> 1;
10056 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10057 ok(FAILED(hr) || broken(formats[i].broken),
10058 "Partial block lock succeeded, expected failure, format %s.\n",
10059 formats[i].name);
10060 if (SUCCEEDED(hr))
10062 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10063 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10067 /* Test full block lock */
10068 box.Left = 0;
10069 box.Top = 0;
10070 box.Right = formats[i].block_width;
10071 box.Bottom = formats[i].block_height;
10072 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10073 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10074 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10075 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10077 IDirect3DVolumeTexture9_Release(texture);
10079 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
10080 * does not allocate surfaces smaller than the blocksize properly. */
10081 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
10083 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
10084 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
10085 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10087 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
10088 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10089 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10090 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10092 box.Left = box.Top = box.Front = 0;
10093 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
10094 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
10095 box.Back = 1;
10096 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10097 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10098 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10099 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10101 box.Right = formats[i].block_width;
10102 box.Bottom = formats[i].block_height;
10103 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10104 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10105 if (SUCCEEDED(hr))
10106 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10108 IDirect3DVolumeTexture9_Release(texture);
10112 refcount = IDirect3DDevice9_Release(device);
10113 ok(!refcount, "Device has %u references left.\n", refcount);
10114 IDirect3D9_Release(d3d9);
10115 DestroyWindow(window);
10118 static void test_lockbox_invalid(void)
10120 static const struct
10122 D3DBOX box;
10123 HRESULT result;
10125 test_data[] =
10127 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
10128 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
10129 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
10130 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
10131 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
10132 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
10133 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
10134 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
10135 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
10136 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
10137 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
10138 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
10139 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
10140 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
10142 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
10143 IDirect3DVolumeTexture9 *texture = NULL;
10144 D3DLOCKED_BOX locked_box;
10145 IDirect3DDevice9 *device;
10146 IDirect3D9 *d3d;
10147 unsigned int i;
10148 ULONG refcount;
10149 HWND window;
10150 BYTE *base;
10151 HRESULT hr;
10153 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10154 0, 0, 640, 480, 0, 0, 0, 0);
10155 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10156 ok(!!d3d, "Failed to create a D3D object.\n");
10157 if (!(device = create_device(d3d, window, NULL)))
10159 skip("Failed to create a D3D device, skipping tests.\n");
10160 IDirect3D9_Release(d3d);
10161 DestroyWindow(window);
10162 return;
10165 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
10166 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
10167 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10168 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10169 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10170 base = locked_box.pBits;
10171 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10172 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10174 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10176 unsigned int offset, expected_offset;
10177 const D3DBOX *box = &test_data[i].box;
10179 locked_box.pBits = (BYTE *)0xdeadbeef;
10180 locked_box.RowPitch = 0xdeadbeef;
10181 locked_box.SlicePitch = 0xdeadbeef;
10183 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
10184 /* Unlike surfaces, volumes properly check the box even in Windows XP */
10185 ok(hr == test_data[i].result,
10186 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
10187 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
10188 test_data[i].result);
10189 if (FAILED(hr))
10190 continue;
10192 offset = (BYTE *)locked_box.pBits - base;
10193 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
10194 ok(offset == expected_offset,
10195 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
10196 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
10198 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10199 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10202 /* locked_box = NULL throws an exception on Windows */
10203 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10204 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10205 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10206 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10207 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10208 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10209 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10210 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10212 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10213 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10214 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10215 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10216 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10217 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10218 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10219 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10220 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
10221 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10222 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
10223 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
10224 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10225 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10227 IDirect3DVolumeTexture9_Release(texture);
10228 refcount = IDirect3DDevice9_Release(device);
10229 ok(!refcount, "Device has %u references left.\n", refcount);
10230 IDirect3D9_Release(d3d);
10231 DestroyWindow(window);
10234 static void test_shared_handle(void)
10236 IDirect3DDevice9 *device;
10237 IDirect3D9 *d3d;
10238 ULONG refcount;
10239 HWND window;
10240 HRESULT hr;
10241 /* Native d3d9ex refuses to create a shared texture if the texture pointer
10242 * is not initialized to NULL. Make sure this doesn't cause issues here. */
10243 IDirect3DTexture9 *texture = NULL;
10244 IDirect3DSurface9 *surface = NULL;
10245 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
10246 IDirect3DIndexBuffer9 *index_buffer = NULL;
10247 HANDLE handle = NULL;
10248 void *mem;
10249 D3DCAPS9 caps;
10251 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10252 0, 0, 640, 480, 0, 0, 0, 0);
10253 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10254 ok(!!d3d, "Failed to create a D3D object.\n");
10255 if (!(device = create_device(d3d, window, NULL)))
10257 skip("Failed to create a D3D device, skipping tests.\n");
10258 IDirect3D9_Release(d3d);
10259 DestroyWindow(window);
10260 return;
10263 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10264 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10265 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
10267 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
10268 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
10269 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10270 D3DPOOL_DEFAULT, &texture, &handle);
10271 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10272 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10273 D3DPOOL_SYSTEMMEM, &texture, &mem);
10274 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10276 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10277 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
10278 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10279 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10280 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
10281 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10283 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10284 &vertex_buffer, &handle);
10285 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10286 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10287 &vertex_buffer, &mem);
10288 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
10290 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10291 &index_buffer, &handle);
10292 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10293 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10294 &index_buffer, &mem);
10295 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10297 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10299 IDirect3DCubeTexture9 *cube_texture = NULL;
10300 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10301 D3DPOOL_DEFAULT, &cube_texture, &handle);
10302 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10303 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10304 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
10305 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10308 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
10310 IDirect3DVolumeTexture9 *volume_texture = NULL;
10311 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10312 D3DPOOL_DEFAULT, &volume_texture, &handle);
10313 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10314 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10315 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
10316 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10319 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
10320 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10321 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10323 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
10324 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10325 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10327 HeapFree(GetProcessHeap(), 0, mem);
10328 refcount = IDirect3DDevice9_Release(device);
10329 ok(!refcount, "Device has %u references left.\n", refcount);
10330 IDirect3D9_Release(d3d);
10331 DestroyWindow(window);
10334 static void test_pixel_format(void)
10336 HWND hwnd, hwnd2 = NULL;
10337 HDC hdc, hdc2 = NULL;
10338 HMODULE gl = NULL;
10339 int format, test_format;
10340 PIXELFORMATDESCRIPTOR pfd;
10341 IDirect3D9 *d3d9 = NULL;
10342 IDirect3DDevice9 *device = NULL;
10343 HRESULT hr;
10344 static const float point[3] = {0.0, 0.0, 0.0};
10346 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10347 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10348 if (!hwnd)
10350 skip("Failed to create window\n");
10351 return;
10354 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10355 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10357 hdc = GetDC(hwnd);
10358 if (!hdc)
10360 skip("Failed to get DC\n");
10361 goto cleanup;
10364 if (hwnd2)
10365 hdc2 = GetDC(hwnd2);
10367 gl = LoadLibraryA("opengl32.dll");
10368 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
10370 format = GetPixelFormat(hdc);
10371 ok(format == 0, "new window has pixel format %d\n", format);
10373 ZeroMemory(&pfd, sizeof(pfd));
10374 pfd.nSize = sizeof(pfd);
10375 pfd.nVersion = 1;
10376 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
10377 pfd.iPixelType = PFD_TYPE_RGBA;
10378 pfd.iLayerType = PFD_MAIN_PLANE;
10379 format = ChoosePixelFormat(hdc, &pfd);
10380 if (format <= 0)
10382 skip("no pixel format available\n");
10383 goto cleanup;
10386 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
10388 skip("failed to set pixel format\n");
10389 goto cleanup;
10392 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
10394 skip("failed to set pixel format on second window\n");
10395 if (hdc2)
10397 ReleaseDC(hwnd2, hdc2);
10398 hdc2 = NULL;
10402 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
10403 ok(!!d3d9, "Failed to create a D3D object.\n");
10405 test_format = GetPixelFormat(hdc);
10406 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10408 if (!(device = create_device(d3d9, hwnd, NULL)))
10410 skip("Failed to create device\n");
10411 goto cleanup;
10414 test_format = GetPixelFormat(hdc);
10415 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10417 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10418 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10420 test_format = GetPixelFormat(hdc);
10421 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10423 hr = IDirect3DDevice9_BeginScene(device);
10424 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
10426 test_format = GetPixelFormat(hdc);
10427 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10429 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
10430 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10432 test_format = GetPixelFormat(hdc);
10433 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10435 hr = IDirect3DDevice9_EndScene(device);
10436 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
10438 test_format = GetPixelFormat(hdc);
10439 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10441 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10442 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10444 test_format = GetPixelFormat(hdc);
10445 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10447 if (hdc2)
10449 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
10450 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10452 test_format = GetPixelFormat(hdc);
10453 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10455 test_format = GetPixelFormat(hdc2);
10456 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
10459 cleanup:
10460 if (device)
10462 UINT refcount = IDirect3DDevice9_Release(device);
10463 ok(!refcount, "Device has %u references left.\n", refcount);
10465 if (d3d9) IDirect3D9_Release(d3d9);
10466 if (gl) FreeLibrary(gl);
10467 if (hdc) ReleaseDC(hwnd, hdc);
10468 if (hdc2) ReleaseDC(hwnd2, hdc2);
10469 if (hwnd) DestroyWindow(hwnd);
10470 if (hwnd2) DestroyWindow(hwnd2);
10473 static void test_begin_end_state_block(void)
10475 IDirect3DStateBlock9 *stateblock;
10476 IDirect3DDevice9 *device;
10477 IDirect3D9 *d3d;
10478 ULONG refcount;
10479 HWND window;
10480 HRESULT hr;
10482 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10483 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10484 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10485 ok(!!d3d, "Failed to create a D3D object.\n");
10486 if (!(device = create_device(d3d, window, NULL)))
10488 skip("Failed to create a D3D device, skipping tests.\n");
10489 IDirect3D9_Release(d3d);
10490 DestroyWindow(window);
10491 return;
10494 /* Should succeed. */
10495 hr = IDirect3DDevice9_BeginStateBlock(device);
10496 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10498 /* Calling BeginStateBlock() while recording should return
10499 * D3DERR_INVALIDCALL. */
10500 hr = IDirect3DDevice9_BeginStateBlock(device);
10501 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10503 /* Should succeed. */
10504 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10505 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10506 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10507 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10508 "Got unexpected stateblock %p.\n", stateblock);
10509 IDirect3DStateBlock9_Release(stateblock);
10511 /* Calling EndStateBlock() while not recording should return
10512 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10513 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10514 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10515 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10516 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10517 "Got unexpected stateblock %p.\n", stateblock);
10519 refcount = IDirect3DDevice9_Release(device);
10520 ok(!refcount, "Device has %u references left.\n", refcount);
10521 IDirect3D9_Release(d3d);
10522 DestroyWindow(window);
10525 static void test_shader_constant_apply(void)
10527 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10528 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10529 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10530 IDirect3DStateBlock9 *stateblock;
10531 DWORD vs_version, ps_version;
10532 IDirect3DDevice9 *device;
10533 IDirect3D9 *d3d;
10534 ULONG refcount;
10535 D3DCAPS9 caps;
10536 float ret[4];
10537 HWND window;
10538 HRESULT hr;
10540 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10541 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10542 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10543 ok(!!d3d, "Failed to create a D3D object.\n");
10544 if (!(device = create_device(d3d, window, NULL)))
10546 skip("Failed to create a D3D device, skipping tests.\n");
10547 IDirect3D9_Release(d3d);
10548 DestroyWindow(window);
10549 return;
10552 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10553 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10554 vs_version = caps.VertexShaderVersion & 0xffff;
10555 ps_version = caps.PixelShaderVersion & 0xffff;
10557 if (vs_version)
10559 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10560 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10561 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10562 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10564 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10565 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10566 ok(!memcmp(ret, initial, sizeof(initial)),
10567 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10568 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10569 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10570 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10571 ok(!memcmp(ret, initial, sizeof(initial)),
10572 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10573 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10575 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10576 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10578 if (ps_version)
10580 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10581 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10582 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10583 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10585 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10586 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10587 ok(!memcmp(ret, initial, sizeof(initial)),
10588 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10589 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10590 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10591 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10592 ok(!memcmp(ret, initial, sizeof(initial)),
10593 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10594 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10596 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10597 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10600 hr = IDirect3DDevice9_BeginStateBlock(device);
10601 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10603 if (vs_version)
10605 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10606 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10608 if (ps_version)
10610 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10611 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10614 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10615 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10617 if (vs_version)
10619 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10620 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10621 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10622 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10623 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10624 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10625 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10626 ok(!memcmp(ret, initial, sizeof(initial)),
10627 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10628 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10630 if (ps_version)
10632 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10633 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10634 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10635 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10636 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10637 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10638 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10639 ok(!memcmp(ret, initial, sizeof(initial)),
10640 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10641 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10644 /* Apply doesn't overwrite constants that aren't explicitly set on the
10645 * source stateblock. */
10646 hr = IDirect3DStateBlock9_Apply(stateblock);
10647 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10649 if (vs_version)
10651 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10652 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10653 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10654 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10655 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10656 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10657 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10658 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10659 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10660 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10662 if (ps_version)
10664 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10665 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10666 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10667 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10668 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10669 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10670 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10671 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10672 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10673 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10676 IDirect3DStateBlock9_Release(stateblock);
10677 refcount = IDirect3DDevice9_Release(device);
10678 ok(!refcount, "Device has %u references left.\n", refcount);
10679 IDirect3D9_Release(d3d);
10680 DestroyWindow(window);
10683 static void test_vdecl_apply(void)
10685 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10686 IDirect3DStateBlock9 *stateblock;
10687 IDirect3DDevice9 *device;
10688 IDirect3D9 *d3d;
10689 ULONG refcount;
10690 HWND window;
10691 HRESULT hr;
10693 static const D3DVERTEXELEMENT9 decl1[] =
10695 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10696 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10697 D3DDECL_END(),
10700 static const D3DVERTEXELEMENT9 decl2[] =
10702 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10703 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10704 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10705 D3DDECL_END(),
10708 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10709 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10710 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10711 ok(!!d3d, "Failed to create a D3D object.\n");
10712 if (!(device = create_device(d3d, window, NULL)))
10714 skip("Failed to create a D3D device, skipping tests.\n");
10715 IDirect3D9_Release(d3d);
10716 DestroyWindow(window);
10717 return;
10720 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10721 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10723 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10724 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10726 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10727 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10728 hr = IDirect3DDevice9_BeginStateBlock(device);
10729 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10730 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10731 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10732 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10733 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10734 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10735 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10736 hr = IDirect3DStateBlock9_Apply(stateblock);
10737 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10738 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10739 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10740 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10741 declaration, declaration1);
10742 IDirect3DVertexDeclaration9_Release(declaration);
10744 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10745 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10746 hr = IDirect3DStateBlock9_Capture(stateblock);
10747 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10748 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10749 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10750 hr = IDirect3DStateBlock9_Apply(stateblock);
10751 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10752 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10753 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10754 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10755 declaration, declaration2);
10756 IDirect3DVertexDeclaration9_Release(declaration);
10758 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10759 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10760 hr = IDirect3DStateBlock9_Capture(stateblock);
10761 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10762 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10763 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10764 hr = IDirect3DStateBlock9_Apply(stateblock);
10765 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10766 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10767 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10768 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10769 declaration, declaration2);
10770 IDirect3DVertexDeclaration9_Release(declaration);
10772 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10773 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10774 hr = IDirect3DStateBlock9_Capture(stateblock);
10775 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10776 hr = IDirect3DStateBlock9_Apply(stateblock);
10777 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10778 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10779 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10780 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10782 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10783 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10784 hr = IDirect3DStateBlock9_Capture(stateblock);
10785 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10786 hr = IDirect3DStateBlock9_Apply(stateblock);
10787 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10788 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10789 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10790 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10791 declaration, declaration2);
10792 IDirect3DVertexDeclaration9_Release(declaration);
10794 IDirect3DStateBlock9_Release(stateblock);
10795 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10796 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10797 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10798 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10799 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10800 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10801 hr = IDirect3DStateBlock9_Apply(stateblock);
10802 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10803 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10804 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10805 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10806 declaration, declaration1);
10807 IDirect3DVertexDeclaration9_Release(declaration);
10809 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10810 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10811 hr = IDirect3DStateBlock9_Capture(stateblock);
10812 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10813 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10814 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10815 hr = IDirect3DStateBlock9_Apply(stateblock);
10816 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10817 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10818 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10819 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10820 declaration, declaration2);
10821 IDirect3DVertexDeclaration9_Release(declaration);
10823 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10824 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10825 hr = IDirect3DStateBlock9_Capture(stateblock);
10826 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10827 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10828 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10829 hr = IDirect3DStateBlock9_Apply(stateblock);
10830 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10831 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10832 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10833 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10834 declaration, declaration2);
10835 IDirect3DVertexDeclaration9_Release(declaration);
10837 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10838 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10839 hr = IDirect3DStateBlock9_Capture(stateblock);
10840 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10841 hr = IDirect3DStateBlock9_Apply(stateblock);
10842 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10843 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10844 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10845 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10847 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10848 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10849 hr = IDirect3DStateBlock9_Capture(stateblock);
10850 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10851 hr = IDirect3DStateBlock9_Apply(stateblock);
10852 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10853 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10854 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10855 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10856 declaration, declaration2);
10857 IDirect3DVertexDeclaration9_Release(declaration);
10859 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10860 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10861 IDirect3DVertexDeclaration9_Release(declaration1);
10862 IDirect3DVertexDeclaration9_Release(declaration2);
10863 IDirect3DStateBlock9_Release(stateblock);
10864 refcount = IDirect3DDevice9_Release(device);
10865 ok(!refcount, "Device has %u references left.\n", refcount);
10866 IDirect3D9_Release(d3d);
10867 DestroyWindow(window);
10870 static void test_resource_type(void)
10872 IDirect3DDevice9 *device;
10873 IDirect3DSurface9 *surface;
10874 IDirect3DTexture9 *texture;
10875 IDirect3DCubeTexture9 *cube_texture;
10876 IDirect3DVolume9 *volume;
10877 IDirect3DVolumeTexture9 *volume_texture;
10878 D3DSURFACE_DESC surface_desc;
10879 D3DVOLUME_DESC volume_desc;
10880 D3DRESOURCETYPE type;
10881 IDirect3D9 *d3d;
10882 ULONG refcount;
10883 HWND window;
10884 HRESULT hr;
10885 D3DCAPS9 caps;
10887 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10888 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10889 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10890 ok(!!d3d, "Failed to create a D3D object.\n");
10891 if (!(device = create_device(d3d, window, NULL)))
10893 skip("Failed to create a D3D device, skipping tests.\n");
10894 IDirect3D9_Release(d3d);
10895 DestroyWindow(window);
10896 return;
10899 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10900 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10902 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10903 D3DPOOL_SYSTEMMEM, &surface, NULL);
10904 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10905 type = IDirect3DSurface9_GetType(surface);
10906 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10907 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10908 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10909 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10910 surface_desc.Type);
10911 IDirect3DSurface9_Release(surface);
10913 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10914 D3DPOOL_SYSTEMMEM, &texture, NULL);
10915 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10916 type = IDirect3DTexture9_GetType(texture);
10917 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10919 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10920 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10921 /* The following code crashes, for the sake of completeness:
10922 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10923 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10925 * So applications will not depend on getting the "right" resource type - whatever it
10926 * may be - from the "wrong" vtable. */
10927 type = IDirect3DSurface9_GetType(surface);
10928 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10929 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10930 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10931 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10932 surface_desc.Type);
10933 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10934 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10935 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10936 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10937 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10938 surface_desc.Type);
10939 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10940 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10941 IDirect3DSurface9_Release(surface);
10943 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10944 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10945 type = IDirect3DSurface9_GetType(surface);
10946 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10947 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10948 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10949 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10950 surface_desc.Type);
10951 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10952 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10953 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10954 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10955 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10956 surface_desc.Type);
10957 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10958 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10959 IDirect3DSurface9_Release(surface);
10960 IDirect3DTexture9_Release(texture);
10962 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10964 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10965 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10966 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10967 type = IDirect3DCubeTexture9_GetType(cube_texture);
10968 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10970 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10971 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10972 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10973 type = IDirect3DSurface9_GetType(surface);
10974 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10975 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10976 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10977 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10978 surface_desc.Type);
10979 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10980 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10981 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10982 surface_desc.Type);
10983 IDirect3DSurface9_Release(surface);
10984 IDirect3DCubeTexture9_Release(cube_texture);
10986 else
10987 skip("Cube maps not supported.\n");
10989 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10991 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10992 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10993 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10994 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10995 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10997 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10998 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10999 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
11000 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
11001 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
11002 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11003 volume_desc.Type);
11004 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
11005 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
11006 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
11007 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
11008 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
11009 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11010 volume_desc.Type);
11011 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
11012 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
11013 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
11014 IDirect3DVolume9_Release(volume);
11016 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
11017 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
11018 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
11019 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
11020 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
11021 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11022 volume_desc.Type);
11023 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
11024 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
11025 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
11026 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
11027 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
11028 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11029 volume_desc.Type);
11030 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
11031 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
11032 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
11033 IDirect3DVolume9_Release(volume);
11034 IDirect3DVolumeTexture9_Release(volume_texture);
11036 else
11037 skip("Mipmapped volume maps not supported.\n");
11039 refcount = IDirect3DDevice9_Release(device);
11040 ok(!refcount, "Device has %u references left.\n", refcount);
11041 IDirect3D9_Release(d3d);
11042 DestroyWindow(window);
11045 static void test_mipmap_lock(void)
11047 IDirect3DDevice9 *device;
11048 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
11049 IDirect3DTexture9 *texture, *texture_dst;
11050 IDirect3D9 *d3d;
11051 ULONG refcount;
11052 HWND window;
11053 HRESULT hr;
11054 D3DLOCKED_RECT locked_rect;
11056 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11057 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11058 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11059 ok(!!d3d, "Failed to create a D3D object.\n");
11060 if (!(device = create_device(d3d, window, NULL)))
11062 skip("Failed to create a D3D device, skipping tests.\n");
11063 IDirect3D9_Release(d3d);
11064 DestroyWindow(window);
11065 return;
11068 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11069 D3DPOOL_DEFAULT, &texture_dst, NULL);
11070 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11071 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
11072 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11073 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
11074 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11076 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11077 D3DPOOL_SYSTEMMEM, &texture, NULL);
11078 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11079 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11080 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11081 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
11082 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11084 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
11085 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11086 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
11087 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11088 hr = IDirect3DSurface9_UnlockRect(surface);
11089 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11091 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
11092 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
11093 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
11094 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11096 /* Apparently there's no validation on the container. */
11097 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
11098 (IDirect3DBaseTexture9 *)texture_dst);
11099 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
11101 hr = IDirect3DSurface9_UnlockRect(surface2);
11102 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11104 IDirect3DSurface9_Release(surface_dst2);
11105 IDirect3DSurface9_Release(surface_dst);
11106 IDirect3DSurface9_Release(surface2);
11107 IDirect3DSurface9_Release(surface);
11108 IDirect3DTexture9_Release(texture_dst);
11109 IDirect3DTexture9_Release(texture);
11111 refcount = IDirect3DDevice9_Release(device);
11112 ok(!refcount, "Device has %u references left.\n", refcount);
11113 IDirect3D9_Release(d3d);
11114 DestroyWindow(window);
11117 static void test_writeonly_resource(void)
11119 IDirect3D9 *d3d;
11120 IDirect3DDevice9 *device;
11121 IDirect3DVertexBuffer9 *buffer;
11122 ULONG refcount;
11123 HWND window;
11124 HRESULT hr;
11125 void *ptr;
11126 static const struct
11128 struct vec3 pos;
11130 quad[] =
11132 {{-1.0f, -1.0f, 0.0f}},
11133 {{-1.0f, 1.0f, 0.0f}},
11134 {{ 1.0f, -1.0f, 0.0f}},
11135 {{ 1.0f, 1.0f, 0.0f}}
11138 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11139 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11140 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11141 ok(!!d3d, "Failed to create a D3D object.\n");
11142 if (!(device = create_device(d3d, window, NULL)))
11144 skip("Failed to create a D3D device, skipping tests.\n");
11145 IDirect3D9_Release(d3d);
11146 DestroyWindow(window);
11147 return;
11150 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
11151 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
11152 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
11154 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
11155 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11156 memcpy(ptr, quad, sizeof(quad));
11157 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11158 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11159 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
11160 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
11161 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
11162 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
11164 hr = IDirect3DDevice9_BeginScene(device);
11165 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
11166 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
11167 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11168 hr = IDirect3DDevice9_EndScene(device);
11169 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
11171 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
11172 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11173 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11174 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11175 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11177 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
11178 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11179 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11180 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11181 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11183 refcount = IDirect3DVertexBuffer9_Release(buffer);
11184 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
11185 refcount = IDirect3DDevice9_Release(device);
11186 ok(!refcount, "Device has %u references left.\n", refcount);
11187 IDirect3D9_Release(d3d);
11188 DestroyWindow(window);
11191 static void test_lost_device(void)
11193 struct device_desc device_desc;
11194 IDirect3DDevice9 *device;
11195 IDirect3D9 *d3d;
11196 ULONG refcount;
11197 HWND window;
11198 HRESULT hr;
11199 BOOL ret;
11201 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11202 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11203 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11204 ok(!!d3d, "Failed to create a D3D object.\n");
11205 device_desc.device_window = window;
11206 device_desc.width = registry_mode.dmPelsWidth;
11207 device_desc.height = registry_mode.dmPelsHeight;
11208 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11209 if (!(device = create_device(d3d, window, &device_desc)))
11211 skip("Failed to create a D3D device, skipping tests.\n");
11212 goto done;
11215 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11216 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11217 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11218 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11220 ret = SetForegroundWindow(GetDesktopWindow());
11221 ok(ret, "Failed to set foreground window.\n");
11222 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11223 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11224 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11225 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11227 ret = ShowWindow(window, SW_RESTORE);
11228 ok(ret, "Failed to restore window.\n");
11229 ret = SetForegroundWindow(window);
11230 ok(ret, "Failed to set foreground window.\n");
11231 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11232 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
11233 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11234 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11236 hr = reset_device(device, &device_desc);
11237 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11238 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11239 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11240 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11241 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11243 device_desc.flags = 0;
11244 hr = reset_device(device, &device_desc);
11245 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11246 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11247 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11248 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11249 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11251 ret = SetForegroundWindow(GetDesktopWindow());
11252 ok(ret, "Failed to set foreground window.\n");
11253 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11254 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11255 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11256 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11258 ret = ShowWindow(window, SW_RESTORE);
11259 ok(ret, "Failed to restore window.\n");
11260 ret = SetForegroundWindow(window);
11261 ok(ret, "Failed to set foreground window.\n");
11262 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11263 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11264 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11265 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11267 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11268 hr = reset_device(device, &device_desc);
11269 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11270 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11271 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11272 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11273 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11275 ret = SetForegroundWindow(GetDesktopWindow());
11276 ok(ret, "Failed to set foreground window.\n");
11277 hr = reset_device(device, &device_desc);
11278 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11279 ret = ShowWindow(window, SW_RESTORE);
11280 ok(ret, "Failed to restore window.\n");
11281 ret = SetForegroundWindow(window);
11282 ok(ret, "Failed to set foreground window.\n");
11283 hr = reset_device(device, &device_desc);
11284 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11286 refcount = IDirect3DDevice9_Release(device);
11287 ok(!refcount, "Device has %u references left.\n", refcount);
11288 done:
11289 IDirect3D9_Release(d3d);
11290 DestroyWindow(window);
11293 static void test_resource_priority(void)
11295 IDirect3DDevice9 *device;
11296 IDirect3DSurface9 *surface;
11297 IDirect3DTexture9 *texture;
11298 IDirect3DVertexBuffer9 *buffer;
11299 IDirect3D9 *d3d;
11300 ULONG refcount;
11301 HWND window;
11302 HRESULT hr;
11303 static const struct
11305 D3DPOOL pool;
11306 const char *name;
11307 BOOL can_set_priority;
11309 test_data[] =
11311 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
11312 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
11313 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
11314 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
11316 unsigned int i;
11317 DWORD priority;
11319 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11320 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11321 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11322 ok(!!d3d, "Failed to create a D3D object.\n");
11323 if (!(device = create_device(d3d, window, NULL)))
11325 skip("Failed to create a D3D device, skipping tests.\n");
11326 IDirect3D9_Release(d3d);
11327 DestroyWindow(window);
11328 return;
11331 for (i = 0; i < ARRAY_SIZE(test_data); i++)
11333 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
11334 test_data[i].pool, &texture, NULL);
11335 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
11336 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11337 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11339 priority = IDirect3DTexture9_GetPriority(texture);
11340 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11341 priority = IDirect3DTexture9_SetPriority(texture, 1);
11342 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11343 priority = IDirect3DTexture9_GetPriority(texture);
11344 if (test_data[i].can_set_priority)
11346 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11347 priority = IDirect3DTexture9_SetPriority(texture, 2);
11348 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11350 else
11351 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11353 priority = IDirect3DSurface9_GetPriority(surface);
11354 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11355 priority = IDirect3DSurface9_SetPriority(surface, 1);
11356 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11357 priority = IDirect3DSurface9_GetPriority(surface);
11358 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11360 IDirect3DSurface9_Release(surface);
11361 IDirect3DTexture9_Release(texture);
11363 if (test_data[i].pool != D3DPOOL_MANAGED)
11365 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
11366 test_data[i].pool, &surface, NULL);
11367 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
11369 priority = IDirect3DSurface9_GetPriority(surface);
11370 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11371 priority = IDirect3DSurface9_SetPriority(surface, 1);
11372 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11373 priority = IDirect3DSurface9_GetPriority(surface);
11374 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11376 IDirect3DSurface9_Release(surface);
11379 if (test_data[i].pool != D3DPOOL_SCRATCH)
11381 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
11382 test_data[i].pool, &buffer, NULL);
11383 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
11385 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11386 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11387 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
11388 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11389 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11390 if (test_data[i].can_set_priority)
11392 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11393 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
11394 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11396 else
11397 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11399 IDirect3DVertexBuffer9_Release(buffer);
11403 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
11404 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11406 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11407 priority = IDirect3DSurface9_GetPriority(surface);
11408 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11409 priority = IDirect3DSurface9_SetPriority(surface, 1);
11410 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11411 priority = IDirect3DSurface9_GetPriority(surface);
11412 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11414 IDirect3DSurface9_Release(surface);
11416 refcount = IDirect3DDevice9_Release(device);
11417 ok(!refcount, "Device has %u references left.\n", refcount);
11418 IDirect3D9_Release(d3d);
11419 DestroyWindow(window);
11422 static void test_swapchain_parameters(void)
11424 IDirect3DDevice9 *device;
11425 HRESULT hr, expected_hr;
11426 IDirect3D9 *d3d;
11427 D3DCAPS9 caps;
11428 HWND window;
11429 unsigned int i;
11430 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
11431 IDirect3DSwapChain9 *swapchain;
11432 static const struct
11434 BOOL windowed;
11435 UINT backbuffer_count;
11436 D3DSWAPEFFECT swap_effect;
11437 HRESULT hr;
11439 tests[] =
11441 /* Swap effect 0 is not allowed. */
11442 {TRUE, 1, 0, D3DERR_INVALIDCALL},
11443 {FALSE, 1, 0, D3DERR_INVALIDCALL},
11445 /* All (non-ex) swap effects are allowed in
11446 * windowed and fullscreen mode. */
11447 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11448 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11449 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11450 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11451 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11453 /* Only one backbuffer in copy mode. */
11454 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
11455 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11456 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11457 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11459 /* Ok with the others, in fullscreen and windowed mode. */
11460 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11461 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11462 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11463 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11465 /* D3D9Ex swap effects. */
11466 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11467 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11468 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11469 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11470 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11471 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11473 /* 3 is the highest allowed backbuffer count. */
11474 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11475 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11476 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11477 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11478 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11481 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11482 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11483 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11484 ok(!!d3d, "Failed to create a D3D object.\n");
11485 if (!(device = create_device(d3d, window, NULL)))
11487 skip("Failed to create a D3D device, skipping tests.\n");
11488 IDirect3D9_Release(d3d);
11489 DestroyWindow(window);
11490 return;
11492 memset(&caps, 0, sizeof(caps));
11493 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11494 ok(hr == D3D_OK, "Failed to get device caps, hr %#x.\n", hr);
11495 IDirect3DDevice9_Release(device);
11497 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11498 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11499 present_parameters_windowed.hDeviceWindow = window;
11500 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11501 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11502 present_parameters_windowed.Windowed = TRUE;
11503 present_parameters_windowed.BackBufferCount = 1;
11505 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11507 memset(&present_parameters, 0, sizeof(present_parameters));
11508 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11509 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11510 present_parameters.hDeviceWindow = window;
11511 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11513 present_parameters.SwapEffect = tests[i].swap_effect;
11514 present_parameters.Windowed = tests[i].windowed;
11515 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11517 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11518 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11519 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11520 if (SUCCEEDED(hr))
11522 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11524 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11525 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11527 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11528 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11529 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11530 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11531 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11532 bb_count, present_parameters2.BackBufferCount, i);
11533 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11534 tests[i].windowed, present_parameters2.Windowed, i);
11536 IDirect3DSwapChain9_Release(swapchain);
11537 IDirect3DDevice9_Release(device);
11540 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11541 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11542 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11544 memset(&present_parameters, 0, sizeof(present_parameters));
11545 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11546 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11547 present_parameters.hDeviceWindow = window;
11548 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11550 present_parameters.SwapEffect = tests[i].swap_effect;
11551 present_parameters.Windowed = tests[i].windowed;
11552 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11554 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11555 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11557 if (FAILED(hr))
11559 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11560 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11562 IDirect3DDevice9_Release(device);
11565 for (i = 0; i < 10; ++i)
11567 memset(&present_parameters, 0, sizeof(present_parameters));
11568 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11569 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11570 present_parameters.hDeviceWindow = window;
11571 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11572 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
11573 present_parameters.Windowed = FALSE;
11574 present_parameters.BackBufferCount = 2;
11576 present_parameters.PresentationInterval = i;
11577 switch (present_parameters.PresentationInterval)
11579 case D3DPRESENT_INTERVAL_ONE:
11580 case D3DPRESENT_INTERVAL_TWO:
11581 case D3DPRESENT_INTERVAL_THREE:
11582 case D3DPRESENT_INTERVAL_FOUR:
11583 if (!(caps.PresentationIntervals & present_parameters.PresentationInterval))
11584 continue;
11585 /* Fall through */
11586 case D3DPRESENT_INTERVAL_DEFAULT:
11587 expected_hr = D3D_OK;
11588 break;
11589 default:
11590 expected_hr = D3DERR_INVALIDCALL;
11591 break;
11594 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11595 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11596 ok(hr == expected_hr, "Got unexpected hr %#x, test %u.\n", hr, i);
11597 if (FAILED(hr))
11598 continue;
11600 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11601 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11603 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11604 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11605 ok(present_parameters2.PresentationInterval == i,
11606 "Got presentation interval %#x, expected %#x.\n",
11607 present_parameters2.PresentationInterval, i);
11609 IDirect3DSwapChain9_Release(swapchain);
11610 IDirect3DDevice9_Release(device);
11613 IDirect3D9_Release(d3d);
11614 DestroyWindow(window);
11617 static void test_check_device_format(void)
11619 static const D3DFORMAT adapter_formats[] =
11621 D3DFMT_A8R8G8B8,
11622 D3DFMT_X8R8G8B8,
11624 static const D3DFORMAT mipmap_autogen_formats[] =
11626 D3DFMT_R8G8B8,
11627 D3DFMT_A8R8G8B8,
11628 D3DFMT_X8R8G8B8,
11629 D3DFMT_R5G6B5,
11630 D3DFMT_X1R5G5B5,
11631 D3DFMT_A8P8,
11632 D3DFMT_P8,
11633 D3DFMT_A1R5G5B5,
11634 D3DFMT_A4R4G4B4,
11637 D3DFORMAT adapter_format, format;
11638 BOOL render_target_supported;
11639 D3DDEVTYPE device_type;
11640 unsigned int i, j;
11641 IDirect3D9 *d3d;
11642 HRESULT hr;
11644 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11645 ok(!!d3d, "Failed to create a D3D object.\n");
11647 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11648 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11650 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11652 else
11654 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11655 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11656 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11657 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11658 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11659 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11662 for (device_type = D3DDEVTYPE_HAL; device_type < D3DDEVTYPE_NULLREF; ++device_type)
11664 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11665 0, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11666 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11667 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11668 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
11669 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11670 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11671 0, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
11672 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11673 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11674 0, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
11675 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11678 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11679 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11680 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11681 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11682 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11683 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11684 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11685 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11686 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11688 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11689 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11690 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11691 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11692 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11693 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11694 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11695 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11696 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11698 for (i = 0; i < ARRAY_SIZE(adapter_formats); ++i)
11700 adapter_format = adapter_formats[i];
11702 for (j = 0; j < ARRAY_SIZE(mipmap_autogen_formats); ++j)
11704 format = mipmap_autogen_formats[j];
11706 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, adapter_format,
11707 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, format);
11708 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
11709 render_target_supported = hr == D3D_OK;
11711 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, adapter_format,
11712 D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, format);
11713 if (render_target_supported)
11715 ok(hr == D3D_OK || hr == D3DOK_NOAUTOGEN, "Got unexpected hr %#x.\n", hr);
11717 else
11719 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
11724 IDirect3D9_Release(d3d);
11727 static void test_miptree_layout(void)
11729 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11730 IDirect3DCubeTexture9 *texture_cube;
11731 IDirect3DTexture9 *texture_2d;
11732 IDirect3DDevice9 *device;
11733 D3DLOCKED_RECT map_desc;
11734 BYTE *base = NULL;
11735 IDirect3D9 *d3d;
11736 D3DCAPS9 caps;
11737 UINT refcount;
11738 HWND window;
11739 HRESULT hr;
11741 static const struct
11743 D3DFORMAT format;
11744 const char *name;
11746 formats[] =
11748 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11749 {D3DFMT_A8, "D3DFMT_A8"},
11750 {D3DFMT_L8, "D3DFMT_L8"},
11751 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11752 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11754 static const struct
11756 D3DPOOL pool;
11757 const char *name;
11759 pools[] =
11761 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11762 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11763 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11766 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11767 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11768 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11769 ok(!!d3d, "Failed to create a D3D object.\n");
11770 if (!(device = create_device(d3d, window, NULL)))
11772 skip("Failed to create a D3D device, skipping tests.\n");
11773 goto done;
11776 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11777 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11779 base_dimension = 257;
11780 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11782 skip("Using power of two base dimension.\n");
11783 base_dimension = 256;
11786 for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx)
11788 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11789 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11791 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11792 continue;
11795 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11797 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11798 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11799 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11800 pools[pool_idx].name, formats[format_idx].name, hr);
11802 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11803 for (i = 0, offset = 0; i < level_count; ++i)
11805 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11806 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11807 pools[pool_idx].name, formats[format_idx].name, i, hr);
11809 if (!i)
11810 base = map_desc.pBits;
11811 else
11812 ok(map_desc.pBits == base + offset,
11813 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11814 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11815 offset += (base_dimension >> i) * map_desc.Pitch;
11817 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11818 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11819 pools[pool_idx].name, formats[format_idx].name, i, hr);
11822 IDirect3DTexture9_Release(texture_2d);
11825 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11826 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11828 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11829 continue;
11832 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11834 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11835 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11836 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11837 pools[pool_idx].name, formats[format_idx].name, hr);
11839 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11840 for (i = 0, offset = 0; i < 6; ++i)
11842 for (j = 0; j < level_count; ++j)
11844 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11845 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11846 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11848 if (!i && !j)
11849 base = map_desc.pBits;
11850 else
11851 ok(map_desc.pBits == base + offset,
11852 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11853 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11854 offset += (base_dimension >> j) * map_desc.Pitch;
11856 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11857 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11858 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11860 offset = (offset + 15) & ~15;
11863 IDirect3DCubeTexture9_Release(texture_cube);
11867 refcount = IDirect3DDevice9_Release(device);
11868 ok(!refcount, "Device has %u references left.\n", refcount);
11869 done:
11870 IDirect3D9_Release(d3d);
11871 DestroyWindow(window);
11874 static void test_get_render_target_data(void)
11876 IDirect3DSurface9 *offscreen_surface, *render_target;
11877 IDirect3DDevice9 *device;
11878 IDirect3D9 *d3d;
11879 UINT refcount;
11880 HWND window;
11881 HRESULT hr;
11883 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11884 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11885 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11886 ok(!!d3d, "Failed to create a D3D object.\n");
11887 if (!(device = create_device(d3d, window, NULL)))
11889 skip("Failed to create a D3D device.\n");
11890 IDirect3D9_Release(d3d);
11891 DestroyWindow(window);
11892 return;
11895 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11896 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11897 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11899 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11900 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11901 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11903 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11904 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11906 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11907 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11909 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11910 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11912 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11913 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11915 IDirect3DSurface9_Release(render_target);
11916 IDirect3DSurface9_Release(offscreen_surface);
11917 refcount = IDirect3DDevice9_Release(device);
11918 ok(!refcount, "Device has %u references left.\n", refcount);
11919 IDirect3D9_Release(d3d);
11920 DestroyWindow(window);
11923 static void test_render_target_device_mismatch(void)
11925 IDirect3DDevice9 *device, *device2;
11926 IDirect3DSurface9 *surface, *rt;
11927 IDirect3D9 *d3d;
11928 UINT refcount;
11929 HWND window;
11930 HRESULT hr;
11932 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11933 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11934 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11935 ok(!!d3d, "Failed to create a D3D object.\n");
11936 if (!(device = create_device(d3d, window, NULL)))
11938 skip("Failed to create a D3D device.\n");
11939 IDirect3D9_Release(d3d);
11940 DestroyWindow(window);
11941 return;
11944 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
11945 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11947 device2 = create_device(d3d, window, NULL);
11948 ok(!!device2, "Failed to create a D3D device.\n");
11950 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11951 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11952 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11954 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11955 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11957 IDirect3DSurface9_Release(surface);
11959 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11960 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11962 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11963 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11965 IDirect3DSurface9_Release(surface);
11967 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11968 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11969 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11970 IDirect3DSurface9_Release(surface);
11971 IDirect3DSurface9_Release(rt);
11973 refcount = IDirect3DDevice9_Release(device);
11974 ok(!refcount, "Device has %u references left.\n", refcount);
11975 refcount = IDirect3DDevice9_Release(device2);
11976 ok(!refcount, "Device has %u references left.\n", refcount);
11977 IDirect3D9_Release(d3d);
11978 DestroyWindow(window);
11981 static void test_format_unknown(void)
11983 IDirect3DDevice9 *device;
11984 IDirect3D9 *d3d;
11985 UINT refcount;
11986 HWND window;
11987 void *iface;
11988 HRESULT hr;
11990 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11991 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11992 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11993 ok(!!d3d, "Failed to create a D3D object.\n");
11994 if (!(device = create_device(d3d, window, NULL)))
11996 skip("Failed to create a D3D device.\n");
11997 IDirect3D9_Release(d3d);
11998 DestroyWindow(window);
11999 return;
12002 iface = (void *)0xdeadbeef;
12003 hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64,
12004 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
12005 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12006 ok(!iface, "Got unexpected iface %p.\n", iface);
12008 iface = (void *)0xdeadbeef;
12009 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 64, 64,
12010 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
12011 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12012 ok(!iface, "Got unexpected iface %p.\n", iface);
12014 iface = (void *)0xdeadbeef;
12015 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
12016 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
12017 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12018 ok(!iface, "Got unexpected iface %p.\n", iface);
12020 iface = (void *)0xdeadbeef;
12021 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
12022 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
12023 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12024 ok(!iface, "Got unexpected iface %p.\n", iface);
12026 iface = (void *)0xdeadbeef;
12027 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 1, 0,
12028 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
12029 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12030 ok(!iface, "Got unexpected iface %p.\n", iface);
12032 iface = (void *)0xdeadbeef;
12033 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
12034 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
12035 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12036 ok(!iface, "Got unexpected iface %p.\n", iface);
12038 refcount = IDirect3DDevice9_Release(device);
12039 ok(!refcount, "Device has %u references left.\n", refcount);
12040 IDirect3D9_Release(d3d);
12041 DestroyWindow(window);
12044 static void test_destroyed_window(void)
12046 IDirect3DDevice9 *device;
12047 IDirect3D9 *d3d9;
12048 ULONG refcount;
12049 HWND window;
12050 HRESULT hr;
12052 /* No WS_VISIBLE. */
12053 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
12054 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12055 ok(!!window, "Failed to create a window.\n");
12057 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
12058 ok(!!d3d9, "Failed to create a D3D object.\n");
12059 device = create_device(d3d9, window, NULL);
12060 IDirect3D9_Release(d3d9);
12061 DestroyWindow(window);
12062 if (!device)
12064 skip("Failed to create a 3D device, skipping test.\n");
12065 return;
12068 hr = IDirect3DDevice9_BeginScene(device);
12069 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12070 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
12071 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12072 hr = IDirect3DDevice9_EndScene(device);
12073 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12074 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12075 ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
12077 refcount = IDirect3DDevice9_Release(device);
12078 ok(!refcount, "Device has %u references left.\n", refcount);
12081 static void test_lockable_backbuffer(void)
12083 D3DPRESENT_PARAMETERS present_parameters = {0};
12084 struct device_desc device_desc;
12085 IDirect3DSurface9 *surface;
12086 IDirect3DDevice9 *device;
12087 D3DLOCKED_RECT lockrect;
12088 IDirect3D9 *d3d;
12089 ULONG refcount;
12090 HWND window;
12091 HRESULT hr;
12092 HDC dc;
12094 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
12095 0, 0, 640, 480, 0, 0, 0, 0);
12096 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12097 ok(!!d3d, "Failed to create a D3D object.\n");
12099 if (!(device = create_device(d3d, window, NULL)))
12101 skip("Failed to create a D3D device, skipping tests.\n");
12102 IDirect3D9_Release(d3d);
12103 DestroyWindow(window);
12104 return;
12107 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12108 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12110 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12111 todo_wine
12112 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12114 dc = (void *)0xdeadbeef;
12115 hr = IDirect3DSurface9_GetDC(surface, &dc);
12116 ok(dc == (void *)0xdeadbeef, "Unexpected DC returned.\n");
12117 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12119 IDirect3DSurface9_Release(surface);
12121 /* Reset with D3DPRESENTFLAG_LOCKABLE_BACKBUFFER. */
12122 present_parameters.BackBufferWidth = 640;
12123 present_parameters.BackBufferHeight = 480;
12124 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
12125 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
12126 present_parameters.hDeviceWindow = window;
12127 present_parameters.Windowed = TRUE;
12128 present_parameters.EnableAutoDepthStencil = TRUE;
12129 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
12130 present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
12132 hr = IDirect3DDevice9_Reset(device, &present_parameters);
12133 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
12135 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12136 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12138 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12139 todo_wine
12140 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
12141 hr = IDirect3DSurface9_UnlockRect(surface);
12142 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
12144 IDirect3DSurface9_Release(surface);
12145 refcount = IDirect3DDevice9_Release(device);
12146 ok(!refcount, "Device has %u references left.\n", refcount);
12148 device_desc.width = 640;
12149 device_desc.height = 480;
12150 device_desc.device_window = window;
12151 device_desc.flags = CREATE_DEVICE_LOCKABLE_BACKBUFFER;
12153 device = create_device(d3d, window, &device_desc);
12154 ok(!!device, "Failed to create device.\n");
12156 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12157 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12159 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12160 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
12161 hr = IDirect3DSurface9_UnlockRect(surface);
12162 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
12164 IDirect3DSurface9_Release(surface);
12165 refcount = IDirect3DDevice9_Release(device);
12166 ok(!refcount, "Device has %u references left.\n", refcount);
12167 IDirect3D9_Release(d3d);
12168 DestroyWindow(window);
12171 static void test_clip_planes_limits(void)
12173 static const DWORD device_flags[] = {0, CREATE_DEVICE_SWVP_ONLY};
12174 IDirect3DDevice9 *device;
12175 struct device_desc desc;
12176 unsigned int i, j;
12177 IDirect3D9 *d3d;
12178 ULONG refcount;
12179 float plane[4];
12180 D3DCAPS9 caps;
12181 DWORD state;
12182 HWND window;
12183 HRESULT hr;
12185 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
12186 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12187 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12188 ok(!!d3d, "Failed to create a D3D object.\n");
12190 for (i = 0; i < ARRAY_SIZE(device_flags); ++i)
12192 desc.device_window = window;
12193 desc.width = 640;
12194 desc.height = 480;
12195 desc.flags = device_flags[i];
12196 if (!(device = create_device(d3d, window, &desc)))
12198 skip("Failed to create D3D device, flags %#x.\n", desc.flags);
12199 continue;
12202 memset(&caps, 0, sizeof(caps));
12203 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12204 ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr);
12206 trace("Max user clip planes: %u.\n", caps.MaxUserClipPlanes);
12208 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12210 memset(plane, 0xff, sizeof(plane));
12211 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12212 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12213 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
12214 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12215 j, plane[0], plane[1], plane[2], plane[3]);
12218 plane[0] = 2.0f;
12219 plane[1] = 8.0f;
12220 plane[2] = 5.0f;
12221 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12223 plane[3] = j;
12224 hr = IDirect3DDevice9_SetClipPlane(device, j, plane);
12225 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", j, hr);
12227 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12229 float expected_d = j >= caps.MaxUserClipPlanes - 1 ? 2 * D3DMAXUSERCLIPPLANES - 1 : j;
12230 memset(plane, 0xff, sizeof(plane));
12231 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12232 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12233 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == expected_d,
12234 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12235 j, plane[0], plane[1], plane[2], plane[3]);
12238 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0xffffffff);
12239 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12240 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12241 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12242 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
12243 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x80000000);
12244 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12245 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12246 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12247 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
12249 refcount = IDirect3DDevice9_Release(device);
12250 ok(!refcount, "Device has %u references left.\n", refcount);
12253 IDirect3D9_Release(d3d);
12254 DestroyWindow(window);
12257 static void test_swapchain_multisample_reset(void)
12259 IDirect3DSwapChain9 *swapchain;
12260 D3DPRESENT_PARAMETERS d3dpp;
12261 IDirect3DDevice9 *device;
12262 DWORD quality_levels;
12263 IDirect3D9 *d3d;
12264 ULONG refcount;
12265 HWND window;
12266 HRESULT hr;
12268 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
12269 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12270 ok(!!window, "Failed to create a window.\n");
12271 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12272 ok(!!d3d, "Failed to create a D3D object.\n");
12274 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12275 D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels) == D3DERR_NOTAVAILABLE)
12277 skip("Multisampling not supported for D3DFMT_A8R8G8B8.\n");
12278 IDirect3D9_Release(d3d);
12279 DestroyWindow(window);
12280 return;
12283 if (!(device = create_device(d3d, window, NULL)))
12285 skip("Failed to create a 3D device.\n");
12286 IDirect3D9_Release(d3d);
12287 DestroyWindow(window);
12288 return;
12291 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
12292 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12294 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
12295 ok(hr == D3D_OK, "Failed to get the implicit swapchain, hr %#x.\n", hr);
12296 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
12297 ok(hr == D3D_OK, "Failed to get present parameters, hr %#x.\n", hr);
12298 ok(d3dpp.MultiSampleType == D3DMULTISAMPLE_NONE,
12299 "Got unexpected multisample type %#x.\n", d3dpp.MultiSampleType);
12300 IDirect3DSwapChain9_Release(swapchain);
12302 d3dpp.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
12303 d3dpp.MultiSampleQuality = quality_levels - 1;
12304 hr = IDirect3DDevice9_Reset(device, &d3dpp);
12305 ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
12307 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
12308 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12310 refcount = IDirect3DDevice9_Release(device);
12311 ok(!refcount, "Device has %u references left.\n", refcount);
12312 IDirect3D9_Release(d3d);
12313 DestroyWindow(window);
12316 static void test_stretch_rect(void)
12318 IDirect3DTexture9 *src_texture, *dst_texture;
12319 IDirect3DSurface9 *src_surface, *dst_surface;
12320 IDirect3DSurface9 *src_rt, *dst_rt;
12321 D3DFORMAT src_format, dst_format;
12322 IDirect3DSurface9 *src, *dst;
12323 D3DPOOL src_pool, dst_pool;
12324 BOOL can_stretch_textures;
12325 IDirect3DDevice9 *device;
12326 HRESULT expected_hr;
12327 unsigned int i, j;
12328 IDirect3D9 *d3d;
12329 ULONG refcount;
12330 D3DCAPS9 caps;
12331 HWND window;
12332 HRESULT hr;
12334 static const D3DFORMAT formats[] =
12336 D3DFMT_A8R8G8B8,
12337 D3DFMT_X8R8G8B8,
12338 D3DFMT_R5G6B5,
12341 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
12342 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12343 ok(!!window, "Failed to create a window.\n");
12344 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12345 ok(!!d3d, "Failed to create a D3D object.\n");
12347 if (!(device = create_device(d3d, window, NULL)))
12349 skip("Failed to create a 3D device.\n");
12350 IDirect3D9_Release(d3d);
12351 DestroyWindow(window);
12352 return;
12355 memset(&caps, 0, sizeof(caps));
12356 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12357 ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr);
12358 can_stretch_textures = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;
12360 for (i = 0; i < ARRAY_SIZE(formats); ++i)
12362 src_format = formats[i];
12363 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12364 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, src_format))
12365 || FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12366 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, src_format)))
12368 skip("Format %#x not supported.\n", src_format);
12369 continue;
12372 for (j = 0; j < ARRAY_SIZE(formats); ++j)
12374 dst_format = formats[j];
12375 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12376 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, dst_format))
12377 || FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12378 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, dst_format)))
12380 skip("Format %#x not supported.\n", dst_format);
12381 continue;
12384 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, src_format,
12385 D3DMULTISAMPLE_NONE, 0, FALSE, &src_rt, NULL);
12386 ok(hr == D3D_OK, "Failed to create render target, hr %#x.\n", hr);
12387 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, dst_format,
12388 D3DMULTISAMPLE_NONE, 0, FALSE, &dst_rt, NULL);
12389 ok(hr == D3D_OK, "Failed to create render target, hr %#x.\n", hr);
12391 hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst_rt, NULL, D3DTEXF_NONE);
12392 ok(hr == D3D_OK, "Got hr %#x (formats %#x/%#x).\n", hr, src_format, dst_format);
12394 for (src_pool = D3DPOOL_DEFAULT; src_pool <= D3DPOOL_SCRATCH; ++src_pool)
12396 for (dst_pool = D3DPOOL_DEFAULT; dst_pool <= D3DPOOL_SCRATCH; ++dst_pool)
12398 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0,
12399 src_format, src_pool, &src_texture, NULL);
12400 ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr);
12401 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0,
12402 dst_format, dst_pool, &dst_texture, NULL);
12403 ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr);
12404 hr = IDirect3DTexture9_GetSurfaceLevel(src_texture, 0, &src);
12405 ok(hr == D3D_OK, "Failed to get surface, hr %#x.\n", hr);
12406 hr = IDirect3DTexture9_GetSurfaceLevel(dst_texture, 0, &dst);
12407 ok(hr == D3D_OK, "Failed to get surface, hr %#x.\n", hr);
12408 IDirect3DTexture9_Release(src_texture);
12409 IDirect3DTexture9_Release(dst_texture);
12411 hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_NONE);
12412 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n",
12413 hr, src_format, dst_format, src_pool, dst_pool);
12415 /* render target <-> texture */
12416 if (src_pool == D3DPOOL_DEFAULT && can_stretch_textures)
12417 expected_hr = D3D_OK;
12418 else
12419 expected_hr = D3DERR_INVALIDCALL;
12420 hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_rt, NULL, D3DTEXF_NONE);
12421 ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n",
12422 hr, expected_hr, src_format, dst_format, src_pool);
12423 hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst, NULL, D3DTEXF_NONE);
12424 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n",
12425 hr, src_format, dst_format, dst_pool);
12427 if (src_pool == D3DPOOL_MANAGED || dst_pool == D3DPOOL_MANAGED)
12429 IDirect3DSurface9_Release(src);
12430 IDirect3DSurface9_Release(dst);
12431 continue;
12434 if (src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT)
12435 expected_hr = D3D_OK;
12436 else
12437 expected_hr = D3DERR_INVALIDCALL;
12439 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
12440 src_format, src_pool, &src_surface, NULL);
12441 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12442 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
12443 dst_format, dst_pool, &dst_surface, NULL);
12444 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12446 hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_surface, NULL, D3DTEXF_NONE);
12447 ok(hr == expected_hr, "Got hr %#x, expected %#x (formats %#x/%#x, pools %#x/%#x).\n",
12448 hr, expected_hr, src_format, dst_format, src_pool, dst_pool);
12450 /* offscreen plain <-> texture */
12451 hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_surface, NULL, D3DTEXF_NONE);
12452 todo_wine_if(src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT)
12453 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n",
12454 hr, src_format, dst_format, src_pool, dst_pool);
12455 hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst, NULL, D3DTEXF_NONE);
12456 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n",
12457 hr, src_format, dst_format, src_pool, dst_pool);
12459 /* offscreen plain <-> render target */
12460 expected_hr = src_pool == D3DPOOL_DEFAULT ? D3D_OK : D3DERR_INVALIDCALL;
12461 hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_rt, NULL, D3DTEXF_NONE);
12462 ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n",
12463 hr, expected_hr, src_format, dst_format, src_pool);
12464 hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst_surface, NULL, D3DTEXF_NONE);
12465 todo_wine_if(dst_pool == D3DPOOL_DEFAULT)
12466 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n",
12467 hr, src_format, dst_format, dst_pool);
12469 IDirect3DSurface9_Release(src_surface);
12470 IDirect3DSurface9_Release(dst_surface);
12472 IDirect3DSurface9_Release(src);
12473 IDirect3DSurface9_Release(dst);
12477 IDirect3DSurface9_Release(src_rt);
12478 IDirect3DSurface9_Release(dst_rt);
12482 refcount = IDirect3DDevice9_Release(device);
12483 ok(!refcount, "Device has %u references left.\n", refcount);
12484 IDirect3D9_Release(d3d);
12485 DestroyWindow(window);
12488 static void test_device_caps(void)
12490 IDirect3DDevice9 *device;
12491 IDirect3D9 *d3d;
12492 ULONG refcount;
12493 D3DCAPS9 caps;
12494 HWND window;
12495 HRESULT hr;
12497 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
12498 0, 0, 640, 480, 0, 0, 0, 0);
12499 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12500 ok(!!d3d, "Failed to create a D3D object.\n");
12502 if (!(device = create_device(d3d, window, NULL)))
12504 skip("Failed to create a D3D device.\n");
12505 IDirect3D9_Release(d3d);
12506 DestroyWindow(window);
12507 return;
12510 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12511 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
12513 ok(!(caps.Caps & ~D3DCAPS_READ_SCANLINE), "Caps field has unexpected flags %#x.\n", caps.Caps);
12514 ok(!(caps.Caps2 & ~(D3DCAPS2_NO2DDURING3DSCENE | D3DCAPS2_FULLSCREENGAMMA
12515 | D3DCAPS2_CANRENDERWINDOWED | D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_RESERVED
12516 | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_CANAUTOGENMIPMAP
12517 | D3DCAPS2_CANSHARERESOURCE)),
12518 "Caps2 field has unexpected flags %#x.\n", caps.Caps2);
12519 /* AMD doesn't filter all the ddraw / d3d9 caps. Consider that behavior
12520 * broken. */
12521 ok(!(caps.Caps3 & ~(D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD
12522 | D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION | D3DCAPS3_COPY_TO_VIDMEM
12523 | D3DCAPS3_COPY_TO_SYSTEMMEM | D3DCAPS3_DXVAHD | D3DCAPS3_DXVAHD_LIMITED
12524 | D3DCAPS3_RESERVED)),
12525 "Caps3 field has unexpected flags %#x.\n", caps.Caps3);
12526 ok(!(caps.PrimitiveMiscCaps & ~(D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP
12527 | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW
12528 | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
12529 | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP
12530 | D3DPMISCCAPS_NULLREFERENCE | D3DPMISCCAPS_INDEPENDENTWRITEMASKS
12531 | D3DPMISCCAPS_PERSTAGECONSTANT | D3DPMISCCAPS_FOGANDSPECULARALPHA
12532 | D3DPMISCCAPS_SEPARATEALPHABLEND | D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
12533 | D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING | D3DPMISCCAPS_FOGVERTEXCLAMPED
12534 | D3DPMISCCAPS_POSTBLENDSRGBCONVERT)),
12535 "PrimitiveMiscCaps field has unexpected flags %#x.\n", caps.PrimitiveMiscCaps);
12536 ok(!(caps.RasterCaps & ~(D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST
12537 | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_ANTIALIASEDGES
12538 | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR
12539 | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER
12540 | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE
12541 | D3DPRASTERCAPS_SCISSORTEST | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
12542 | D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_MULTISAMPLE_TOGGLE)),
12543 "RasterCaps field has unexpected flags %#x.\n", caps.RasterCaps);
12544 /* D3DPBLENDCAPS_SRCCOLOR2 and D3DPBLENDCAPS_INVSRCCOLOR2 are only
12545 * advertised on the reference rasterizer and WARP. */
12546 ok(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12547 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12548 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12549 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12550 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR))
12551 || broken(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12552 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12553 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12554 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12555 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR
12556 | D3DPBLENDCAPS_SRCCOLOR2 | D3DPBLENDCAPS_INVSRCCOLOR2))),
12557 "SrcBlendCaps field has unexpected flags %#x.\n", caps.SrcBlendCaps);
12558 ok(!(caps.DestBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12559 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12560 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12561 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12562 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR))
12563 || broken(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12564 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12565 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12566 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12567 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR
12568 | D3DPBLENDCAPS_SRCCOLOR2 | D3DPBLENDCAPS_INVSRCCOLOR2))),
12569 "DestBlendCaps field has unexpected flags %#x.\n", caps.DestBlendCaps);
12570 ok(!(caps.TextureCaps & ~(D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2
12571 | D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_SQUAREONLY
12572 | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE
12573 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED
12574 | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP | D3DPTEXTURECAPS_MIPMAP
12575 | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP
12576 | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2
12577 | D3DPTEXTURECAPS_NOPROJECTEDBUMPENV)),
12578 "TextureCaps field has unexpected flags %#x.\n", caps.TextureCaps);
12579 ok(!(caps.TextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
12580 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
12581 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
12582 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_CONVOLUTIONMONO
12583 | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
12584 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
12585 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
12586 "TextureFilterCaps field has unexpected flags %#x.\n", caps.TextureFilterCaps);
12587 ok(!(caps.CubeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
12588 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
12589 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
12590 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
12591 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
12592 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
12593 "CubeTextureFilterCaps field has unexpected flags %#x.\n", caps.CubeTextureFilterCaps);
12594 ok(!(caps.VolumeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
12595 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
12596 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
12597 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
12598 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
12599 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
12600 "VolumeTextureFilterCaps field has unexpected flags %#x.\n", caps.VolumeTextureFilterCaps);
12601 ok(!(caps.LineCaps & ~(D3DLINECAPS_TEXTURE | D3DLINECAPS_ZTEST | D3DLINECAPS_BLEND
12602 | D3DLINECAPS_ALPHACMP | D3DLINECAPS_FOG | D3DLINECAPS_ANTIALIAS)),
12603 "LineCaps field has unexpected flags %#x.\n", caps.LineCaps);
12604 ok(!(caps.StencilCaps & ~(D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE
12605 | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT
12606 | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR | D3DSTENCILCAPS_TWOSIDED)),
12607 "StencilCaps field has unexpected flags %#x.\n", caps.StencilCaps);
12608 ok(!(caps.VertexProcessingCaps & ~(D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7
12609 | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER
12610 | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_TEXGEN_SPHEREMAP
12611 | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER)),
12612 "VertexProcessingCaps field has unexpected flags %#x.\n", caps.VertexProcessingCaps);
12613 /* Both Nvidia and AMD give 10 here. */
12614 ok(caps.MaxActiveLights <= 10,
12615 "MaxActiveLights field has unexpected value %u.\n", caps.MaxActiveLights);
12616 /* AMD gives 6, Nvidia returns 8. */
12617 ok(caps.MaxUserClipPlanes <= 8,
12618 "MaxUserClipPlanes field has unexpected value %u.\n", caps.MaxUserClipPlanes);
12620 refcount = IDirect3DDevice9_Release(device);
12621 ok(!refcount, "Device has %u references left.\n", refcount);
12622 IDirect3D9_Release(d3d);
12623 DestroyWindow(window);
12626 START_TEST(device)
12628 WNDCLASSA wc = {0};
12629 IDirect3D9 *d3d9;
12630 DEVMODEW current_mode;
12632 memset(&current_mode, 0, sizeof(current_mode));
12633 current_mode.dmSize = sizeof(current_mode);
12634 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
12635 registry_mode.dmSize = sizeof(registry_mode);
12636 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
12637 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
12638 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
12640 skip("Current mode does not match registry mode, skipping test.\n");
12641 return;
12644 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
12646 skip("could not create D3D9 object\n");
12647 return;
12649 IDirect3D9_Release(d3d9);
12651 wc.lpfnWndProc = DefWindowProcA;
12652 wc.lpszClassName = "d3d9_test_wc";
12653 RegisterClassA(&wc);
12655 test_get_set_vertex_declaration();
12656 test_get_declaration();
12657 test_fvf_decl_conversion();
12658 test_fvf_decl_management();
12659 test_vertex_declaration_alignment();
12660 test_unused_declaration_type();
12661 test_fpu_setup();
12662 test_multi_device();
12663 test_display_formats();
12664 test_display_modes();
12665 test_swapchain();
12666 test_refcount();
12667 test_mipmap_levels();
12668 test_checkdevicemultisampletype();
12669 test_invalid_multisample();
12670 test_cursor();
12671 test_cursor_pos();
12672 test_reset_fullscreen();
12673 test_reset();
12674 test_scene();
12675 test_limits();
12676 test_depthstenciltest();
12677 test_get_rt();
12678 test_draw_primitive();
12679 test_null_stream();
12680 test_lights();
12681 test_set_stream_source();
12682 test_scissor_size();
12683 test_wndproc();
12684 test_wndproc_windowed();
12685 test_window_style();
12686 test_mode_change();
12687 test_device_window_reset();
12688 test_reset_resources();
12689 test_set_rt_vp_scissor();
12690 test_volume_get_container();
12691 test_volume_resource();
12692 test_vb_lock_flags();
12693 test_vertex_buffer_alignment();
12694 test_query_support();
12695 test_occlusion_query();
12696 test_timestamp_query();
12697 test_get_set_vertex_shader();
12698 test_vertex_shader_constant();
12699 test_get_set_pixel_shader();
12700 test_pixel_shader_constant();
12701 test_unsupported_shaders();
12702 test_texture_stage_states();
12703 test_cube_textures();
12704 test_mipmap_gen();
12705 test_filter();
12706 test_get_set_texture();
12707 test_lod();
12708 test_surface_get_container();
12709 test_surface_alignment();
12710 test_lockrect_offset();
12711 test_lockrect_invalid();
12712 test_private_data();
12713 test_getdc();
12714 test_surface_dimensions();
12715 test_surface_format_null();
12716 test_surface_double_unlock();
12717 test_surface_blocks();
12718 test_set_palette();
12719 test_swvp_buffer();
12720 test_managed_buffer();
12721 test_npot_textures();
12722 test_vidmem_accounting();
12723 test_volume_locking();
12724 test_update_volumetexture();
12725 test_create_rt_ds_fail();
12726 test_volume_blocks();
12727 test_lockbox_invalid();
12728 test_shared_handle();
12729 test_pixel_format();
12730 test_begin_end_state_block();
12731 test_shader_constant_apply();
12732 test_vdecl_apply();
12733 test_resource_type();
12734 test_mipmap_lock();
12735 test_writeonly_resource();
12736 test_lost_device();
12737 test_resource_priority();
12738 test_swapchain_parameters();
12739 test_check_device_format();
12740 test_miptree_layout();
12741 test_get_render_target_data();
12742 test_render_target_device_mismatch();
12743 test_format_unknown();
12744 test_destroyed_window();
12745 test_lockable_backbuffer();
12746 test_clip_planes_limits();
12747 test_swapchain_multisample_reset();
12748 test_stretch_rect();
12749 test_device_caps();
12751 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));