msvcirt: Don't return negative values in in_avail and out_waiting.
[wine.git] / dlls / d3d9 / tests / device.c
blob9f1d39bb2f860a50921ec96a2c556d4bfc212236
1 /*
2 * Copyright (C) 2006 Ivan Gyurdiev
3 * Copyright (C) 2006 Vitaliy Margolen
4 * Copyright (C) 2006 Chris Robinson
5 * Copyright 2006-2008, 2010-2011, 2013 Stefan Dösinger for CodeWeavers
6 * Copyright 2005, 2006, 2007 Henri Verbeet
7 * Copyright 2013-2014 Henri Verbeet for CodeWeavers
8 * Copyright (C) 2008 Rico Schüller
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WINVER 0x0602 /* for CURSOR_SUPPRESSED */
26 #define COBJMACROS
27 #include <d3d9.h>
28 #include "wine/test.h"
30 struct vec3
32 float x, y, z;
35 #define CREATE_DEVICE_FULLSCREEN 0x01
36 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
37 #define CREATE_DEVICE_FPU_PRESERVE 0x04
38 #define CREATE_DEVICE_SWVP_ONLY 0x08
40 struct device_desc
42 HWND device_window;
43 unsigned int width;
44 unsigned int height;
45 DWORD flags;
48 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
49 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
51 static DEVMODEW registry_mode;
53 static const DWORD simple_vs[] =
55 0xfffe0101, /* vs_1_1 */
56 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
57 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
58 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
59 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
60 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
61 0x0000ffff, /* end */
64 static const DWORD simple_ps[] =
66 0xffff0101, /* ps_1_1 */
67 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
68 0x00000042, 0xb00f0000, /* tex t0 */
69 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
70 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
71 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
72 0x0000ffff, /* end */
75 static int get_refcount(IUnknown *object)
77 IUnknown_AddRef( object );
78 return IUnknown_Release( object );
81 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
83 unsigned int element_count, i;
84 D3DVERTEXELEMENT9 *elements;
85 BOOL equal = TRUE;
86 HRESULT hr;
88 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
89 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
90 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
91 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
92 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
94 for (i = 0; i < element_count; ++i)
96 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
98 equal = FALSE;
99 break;
103 if (!equal)
105 for (i = 0; i < element_count; ++i)
107 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
108 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
109 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
113 HeapFree(GetProcessHeap(), 0, elements);
114 return equal;
117 /* try to make sure pending X events have been processed before continuing */
118 static void flush_events(void)
120 MSG msg;
121 int diff = 200;
122 int min_timeout = 100;
123 DWORD time = GetTickCount() + diff;
125 while (diff > 0)
127 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
128 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
129 diff = time - GetTickCount();
133 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
135 D3DPRESENT_PARAMETERS present_parameters = {0};
136 IDirect3DDevice9 *device;
137 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
139 present_parameters.BackBufferWidth = 640;
140 present_parameters.BackBufferHeight = 480;
141 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
142 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
143 present_parameters.hDeviceWindow = focus_window;
144 present_parameters.Windowed = TRUE;
145 present_parameters.EnableAutoDepthStencil = TRUE;
146 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
148 if (desc)
150 present_parameters.BackBufferWidth = desc->width;
151 present_parameters.BackBufferHeight = desc->height;
152 present_parameters.hDeviceWindow = desc->device_window;
153 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
154 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
155 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
156 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
157 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
158 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
159 behavior_flags |= D3DCREATE_FPU_PRESERVE;
162 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
163 behavior_flags, &present_parameters, &device)))
164 return device;
166 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
167 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
168 behavior_flags, &present_parameters, &device)))
169 return device;
171 if (desc && desc->flags & CREATE_DEVICE_SWVP_ONLY)
172 return NULL;
173 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
175 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
176 behavior_flags, &present_parameters, &device)))
177 return device;
179 return NULL;
182 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
184 D3DPRESENT_PARAMETERS present_parameters = {0};
186 present_parameters.BackBufferWidth = 640;
187 present_parameters.BackBufferHeight = 480;
188 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
189 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
190 present_parameters.hDeviceWindow = NULL;
191 present_parameters.Windowed = TRUE;
192 present_parameters.EnableAutoDepthStencil = TRUE;
193 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
195 if (desc)
197 present_parameters.BackBufferWidth = desc->width;
198 present_parameters.BackBufferHeight = desc->height;
199 present_parameters.hDeviceWindow = desc->device_window;
200 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
203 return IDirect3DDevice9_Reset(device, &present_parameters);
206 #define CHECK_CALL(r,c,d,rc) \
207 if (SUCCEEDED(r)) {\
208 int tmp1 = get_refcount( (IUnknown *)d ); \
209 int rc_new = rc; \
210 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
211 } else {\
212 trace("%s failed: %08x\n", c, r); \
215 #define CHECK_RELEASE(obj,d,rc) \
216 if (obj) { \
217 int tmp1, rc_new = rc; \
218 IUnknown_Release( (IUnknown*)obj ); \
219 tmp1 = get_refcount( (IUnknown *)d ); \
220 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
223 #define CHECK_REFCOUNT(obj,rc) \
225 int rc_new = rc; \
226 int count = get_refcount( (IUnknown *)obj ); \
227 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
230 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
232 int rc_new = rc; \
233 int count = IUnknown_Release( (IUnknown *)obj ); \
234 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
237 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
239 int rc_new = rc; \
240 int count = IUnknown_AddRef( (IUnknown *)obj ); \
241 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
244 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
246 void *container_ptr = (void *)0x1337c0d3; \
247 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
248 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
249 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
250 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
253 static void test_get_set_vertex_declaration(void)
255 IDirect3DVertexDeclaration9 *declaration, *tmp;
256 ULONG refcount, expected_refcount;
257 IDirect3DDevice9 *device;
258 IDirect3D9 *d3d;
259 HWND window;
260 HRESULT hr;
262 static const D3DVERTEXELEMENT9 simple_decl[] =
264 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
265 D3DDECL_END()
268 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
269 0, 0, 640, 480, NULL, NULL, NULL, NULL);
270 d3d = Direct3DCreate9(D3D_SDK_VERSION);
271 ok(!!d3d, "Failed to create a D3D object.\n");
272 if (!(device = create_device(d3d, window, NULL)))
274 skip("Failed to create a D3D device, skipping tests.\n");
275 goto done;
278 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
279 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
281 /* SetVertexDeclaration() should not touch the declaration's refcount. */
282 expected_refcount = get_refcount((IUnknown *)declaration);
283 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
284 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
285 refcount = get_refcount((IUnknown *)declaration);
286 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
288 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
289 tmp = NULL;
290 expected_refcount = refcount + 1;
291 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
292 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
293 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
294 refcount = get_refcount((IUnknown *)declaration);
295 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
296 IDirect3DVertexDeclaration9_Release(tmp);
298 IDirect3DVertexDeclaration9_Release(declaration);
299 refcount = IDirect3DDevice9_Release(device);
300 ok(!refcount, "Device has %u references left.\n", refcount);
301 done:
302 IDirect3D9_Release(d3d);
303 DestroyWindow(window);
306 static void test_get_declaration(void)
308 unsigned int element_count, expected_element_count;
309 IDirect3DVertexDeclaration9 *declaration;
310 D3DVERTEXELEMENT9 *elements;
311 IDirect3DDevice9 *device;
312 IDirect3D9 *d3d;
313 ULONG refcount;
314 HWND window;
315 HRESULT hr;
317 static const D3DVERTEXELEMENT9 simple_decl[] =
319 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
320 D3DDECL_END()
323 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
324 0, 0, 640, 480, NULL, NULL, NULL, NULL);
325 d3d = Direct3DCreate9(D3D_SDK_VERSION);
326 ok(!!d3d, "Failed to create a D3D object.\n");
327 if (!(device = create_device(d3d, window, NULL)))
329 skip("Failed to create a D3D device, skipping tests.\n");
330 goto done;
333 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
334 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
336 /* First test only getting the number of elements. */
337 element_count = 0x1337c0de;
338 expected_element_count = sizeof(simple_decl) / sizeof(*simple_decl);
339 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
340 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
341 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
342 element_count, expected_element_count);
344 element_count = 0;
345 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
346 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
347 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
348 element_count, expected_element_count);
350 /* Also test the returned data. */
351 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
353 element_count = 0x1337c0de;
354 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
355 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
356 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
357 element_count, expected_element_count);
358 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
359 "Original and returned vertexdeclarations are not the same.\n");
361 memset(elements, 0, sizeof(simple_decl));
363 element_count = 0;
364 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
365 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
366 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
367 element_count, expected_element_count);
368 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
369 "Original and returned vertexdeclarations are not the same.\n");
371 HeapFree(GetProcessHeap(), 0, elements);
372 IDirect3DVertexDeclaration9_Release(declaration);
373 refcount = IDirect3DDevice9_Release(device);
374 ok(!refcount, "Device has %u references left.\n", refcount);
375 done:
376 IDirect3D9_Release(d3d);
377 DestroyWindow(window);
380 static void test_fvf_decl_conversion(void)
382 IDirect3DVertexDeclaration9 *default_decl;
383 IDirect3DVertexDeclaration9 *declaration;
384 IDirect3DDevice9 *device;
385 IDirect3D9 *d3d;
386 ULONG refcount;
387 unsigned int i;
388 HWND window;
389 HRESULT hr;
391 static const D3DVERTEXELEMENT9 default_elements[] =
393 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
394 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
395 D3DDECL_END()
397 /* Test conversions from vertex declaration to an FVF. For some reason
398 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
399 * forced to 0 - maybe this is configuration specific. */
400 static const struct
402 D3DVERTEXELEMENT9 elements[7];
403 DWORD fvf;
404 BOOL todo;
406 decl_to_fvf_tests[] =
408 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
409 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
410 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
411 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
412 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
413 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
414 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
415 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
416 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
417 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
418 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
419 /* No FVF mapping available. */
420 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
421 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
422 /* Try empty declaration. */
423 {{ D3DDECL_END()}, 0, FALSE},
424 /* Make sure textures of different sizes work. */
425 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
426 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
427 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
428 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
429 /* Make sure the TEXCOORD index works correctly - try several textures. */
432 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
433 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
434 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
435 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
436 D3DDECL_END(),
437 }, 0, FALSE,
439 /* Now try a combination test. */
442 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
443 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
444 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
445 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
446 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
447 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
448 D3DDECL_END(),
449 }, 0, FALSE,
452 /* Test conversions from FVF to a vertex declaration. These seem to always
453 * occur internally. A new declaration object is created if necessary. */
454 static const struct
456 DWORD fvf;
457 D3DVERTEXELEMENT9 elements[7];
459 fvf_to_decl_tests[] =
461 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
462 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
463 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
465 D3DFVF_XYZB5,
467 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
468 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
469 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
470 D3DDECL_END(),
474 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
476 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
477 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
478 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
479 D3DDECL_END(),
483 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
485 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
486 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
487 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
488 D3DDECL_END(),
492 D3DFVF_XYZB1,
494 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
495 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
496 D3DDECL_END(),
500 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
502 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
503 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
504 D3DDECL_END(),
508 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
510 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
511 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
512 D3DDECL_END(),
516 D3DFVF_XYZB2,
518 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
519 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
520 D3DDECL_END(),
524 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
526 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
527 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
528 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
529 D3DDECL_END(),
533 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
535 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
536 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
537 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
538 D3DDECL_END(),
542 D3DFVF_XYZB3,
544 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
545 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
546 D3DDECL_END(),
550 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
552 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
553 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
554 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
555 D3DDECL_END(),
559 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
561 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
562 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
563 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
564 D3DDECL_END(),
568 D3DFVF_XYZB4,
570 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
571 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
572 D3DDECL_END(),
576 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
578 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
579 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
580 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
581 D3DDECL_END(),
585 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
587 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
588 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
589 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
590 D3DDECL_END(),
593 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
594 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
595 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
596 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
597 /* Make sure textures of different sizes work. */
599 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
600 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
603 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
604 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
607 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
608 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
611 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
612 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
614 /* Make sure the TEXCOORD index works correctly - try several textures. */
616 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
617 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
619 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
620 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
621 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
622 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
623 D3DDECL_END(),
626 /* Now try a combination test. */
628 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
629 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
631 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
632 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
633 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
634 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
635 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
636 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
637 D3DDECL_END(),
642 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
643 0, 0, 640, 480, NULL, NULL, NULL, NULL);
644 d3d = Direct3DCreate9(D3D_SDK_VERSION);
645 ok(!!d3d, "Failed to create a D3D object.\n");
646 if (!(device = create_device(d3d, window, NULL)))
648 skip("Failed to create a D3D device, skipping tests.\n");
649 goto done;
652 for (i = 0; i < sizeof(decl_to_fvf_tests) / sizeof(*decl_to_fvf_tests); ++i)
654 DWORD fvf = 0xdeadbeef;
655 HRESULT hr;
657 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
658 * back to 0. */
659 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
660 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
662 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
663 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
664 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
665 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
667 /* Check the FVF. */
668 hr = IDirect3DDevice9_GetFVF(device, &fvf);
669 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
671 todo_wine_if (decl_to_fvf_tests[i].todo)
672 ok(fvf == decl_to_fvf_tests[i].fvf,
673 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
674 i, fvf, decl_to_fvf_tests[i].fvf);
676 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
677 IDirect3DVertexDeclaration9_Release(declaration);
680 /* Create a default declaration and FVF that does not match any of the
681 * tests. */
682 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
683 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
685 for (i = 0; i < sizeof(fvf_to_decl_tests) / sizeof(*fvf_to_decl_tests); ++i)
687 /* Set a default declaration to make sure it is changed. */
688 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
689 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
691 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
692 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
694 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
695 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
696 ok(!!declaration && declaration != default_decl,
697 "Test %u: Got unexpected declaration %p.\n", i, declaration);
698 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
699 "Test %u: Declaration does not match.\n", i);
700 IDirect3DVertexDeclaration9_Release(declaration);
703 /* Setting the FVF to 0 should result in no change to the default decl. */
704 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
705 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
706 hr = IDirect3DDevice9_SetFVF(device, 0);
707 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
708 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
709 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
710 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
711 IDirect3DVertexDeclaration9_Release(declaration);
713 IDirect3DVertexDeclaration9_Release(default_decl);
714 refcount = IDirect3DDevice9_Release(device);
715 ok(!refcount, "Device has %u references left.\n", refcount);
716 done:
717 IDirect3D9_Release(d3d);
718 DestroyWindow(window);
721 /* Check whether a declaration converted from FVF is shared.
722 * Check whether refcounts behave as expected. */
723 static void test_fvf_decl_management(void)
725 IDirect3DVertexDeclaration9 *declaration1;
726 IDirect3DVertexDeclaration9 *declaration2;
727 IDirect3DVertexDeclaration9 *declaration3;
728 IDirect3DVertexDeclaration9 *declaration4;
729 IDirect3DDevice9 *device;
730 IDirect3D9 *d3d;
731 ULONG refcount;
732 HWND window;
733 HRESULT hr;
735 static const D3DVERTEXELEMENT9 test_elements1[] =
736 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
737 static const D3DVERTEXELEMENT9 test_elements2[] =
738 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
740 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
741 0, 0, 640, 480, NULL, NULL, NULL, NULL);
742 d3d = Direct3DCreate9(D3D_SDK_VERSION);
743 ok(!!d3d, "Failed to create a D3D object.\n");
744 if (!(device = create_device(d3d, window, NULL)))
746 skip("Failed to create a D3D device, skipping tests.\n");
747 goto done;
750 /* Clear down any current vertex declaration. */
751 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
752 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
753 /* Conversion. */
754 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
755 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
756 /* Get converted decl (#1). */
757 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
758 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
759 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
760 /* Get converted decl again (#2). */
761 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
762 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
763 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
765 /* Conversion. */
766 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
767 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
768 /* Get converted decl (#3). */
769 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
770 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
771 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
772 /* The contents should correspond to the second conversion. */
773 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
774 /* Re-Check if the first decl was overwritten by the new Get(). */
775 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
777 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
778 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
779 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
780 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
781 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
783 refcount = get_refcount((IUnknown*)declaration1);
784 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
785 refcount = get_refcount((IUnknown*)declaration2);
786 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
787 refcount = get_refcount((IUnknown*)declaration3);
788 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
789 refcount = get_refcount((IUnknown*)declaration4);
790 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
792 IDirect3DVertexDeclaration9_Release(declaration4);
793 IDirect3DVertexDeclaration9_Release(declaration3);
794 IDirect3DVertexDeclaration9_Release(declaration2);
795 IDirect3DVertexDeclaration9_Release(declaration1);
797 refcount = IDirect3DDevice9_Release(device);
798 ok(!refcount, "Device has %u references left.\n", refcount);
799 done:
800 IDirect3D9_Release(d3d);
801 DestroyWindow(window);
804 static void test_vertex_declaration_alignment(void)
806 IDirect3DVertexDeclaration9 *declaration;
807 IDirect3DDevice9 *device;
808 IDirect3D9 *d3d;
809 unsigned int i;
810 ULONG refcount;
811 HWND window;
812 HRESULT hr;
814 static const struct
816 D3DVERTEXELEMENT9 elements[3];
817 HRESULT hr;
819 test_data[] =
823 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
824 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
825 D3DDECL_END(),
826 }, D3D_OK,
830 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
831 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
832 D3DDECL_END(),
833 }, E_FAIL,
837 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
838 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
839 D3DDECL_END(),
840 }, E_FAIL,
844 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
845 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
846 D3DDECL_END(),
847 }, E_FAIL,
851 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
852 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
853 D3DDECL_END(),
854 }, D3D_OK,
858 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
859 0, 0, 640, 480, NULL, NULL, NULL, NULL);
860 d3d = Direct3DCreate9(D3D_SDK_VERSION);
861 ok(!!d3d, "Failed to create a D3D object.\n");
862 if (!(device = create_device(d3d, window, NULL)))
864 skip("Failed to create a D3D device, skipping tests.\n");
865 goto done;
868 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
870 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
871 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
872 if (SUCCEEDED(hr))
873 IDirect3DVertexDeclaration9_Release(declaration);
876 refcount = IDirect3DDevice9_Release(device);
877 ok(!refcount, "Device has %u references left.\n", refcount);
878 done:
879 IDirect3D9_Release(d3d);
880 DestroyWindow(window);
883 static void test_unused_declaration_type(void)
885 IDirect3DVertexDeclaration9 *declaration;
886 IDirect3DDevice9 *device;
887 IDirect3D9 *d3d;
888 unsigned int i;
889 ULONG refcount;
890 HWND window;
891 HRESULT hr;
893 static const D3DVERTEXELEMENT9 test_elements[][3] =
896 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
897 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
898 D3DDECL_END(),
901 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
902 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
903 D3DDECL_END(),
906 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
907 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
908 D3DDECL_END(),
911 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
912 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
913 D3DDECL_END(),
916 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
917 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
918 D3DDECL_END(),
921 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
922 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
923 D3DDECL_END(),
926 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
927 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
928 D3DDECL_END(),
932 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
933 0, 0, 640, 480, NULL, NULL, NULL, NULL);
934 d3d = Direct3DCreate9(D3D_SDK_VERSION);
935 ok(!!d3d, "Failed to create a D3D object.\n");
936 if (!(device = create_device(d3d, window, NULL)))
938 skip("Failed to create a D3D device, skipping tests.\n");
939 goto done;
942 for (i = 0; i < sizeof(test_elements) / sizeof(*test_elements); ++i)
944 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
945 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
948 refcount = IDirect3DDevice9_Release(device);
949 ok(!refcount, "Device has %u references left.\n", refcount);
950 done:
951 IDirect3D9_Release(d3d);
952 DestroyWindow(window);
955 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
957 IDirect3DBaseTexture9* texture = NULL;
958 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
959 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
961 if (SUCCEEDED(hr)) {
962 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
963 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
964 } else
965 trace("CreateTexture failed: %08x\n", hr);
967 if (texture) IDirect3DBaseTexture9_Release( texture );
970 static void test_mipmap_levels(void)
972 IDirect3DDevice9 *device;
973 IDirect3D9 *d3d;
974 ULONG refcount;
975 HWND window;
977 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
978 0, 0, 640, 480, NULL, NULL, NULL, NULL);
979 ok(!!window, "Failed to create a window.\n");
980 d3d = Direct3DCreate9(D3D_SDK_VERSION);
981 ok(!!d3d, "Failed to create a D3D object.\n");
982 if (!(device = create_device(d3d, window, NULL)))
984 skip("Failed to create a 3D device, skipping test.\n");
985 goto cleanup;
988 check_mipmap_levels(device, 32, 32, 6);
989 check_mipmap_levels(device, 256, 1, 9);
990 check_mipmap_levels(device, 1, 256, 9);
991 check_mipmap_levels(device, 1, 1, 1);
993 refcount = IDirect3DDevice9_Release(device);
994 ok(!refcount, "Device has %u references left.\n", refcount);
995 cleanup:
996 IDirect3D9_Release(d3d);
997 DestroyWindow(window);
1000 static void test_checkdevicemultisampletype(void)
1002 DWORD quality_levels;
1003 IDirect3D9 *d3d;
1004 HWND window;
1005 HRESULT hr;
1007 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1008 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1009 ok(!!window, "Failed to create a window.\n");
1010 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1011 ok(!!d3d, "Failed to create a D3D object.\n");
1013 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1014 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL) == D3DERR_NOTAVAILABLE)
1016 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
1017 goto cleanup;
1020 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1021 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE, NULL);
1022 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1023 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1024 65536, TRUE, D3DMULTISAMPLE_NONE, NULL);
1025 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1027 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1028 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, NULL);
1029 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1031 quality_levels = 0;
1032 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1033 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1034 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1035 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1036 quality_levels = 0;
1037 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1038 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1039 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1040 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1042 quality_levels = 0;
1043 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1044 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, NULL);
1045 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1046 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1047 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels);
1048 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1049 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1051 quality_levels = 0;
1052 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1053 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1054 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1055 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1056 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels);
1057 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1058 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1060 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1061 quality_levels = 0;
1062 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1063 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1064 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1065 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1066 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, &quality_levels);
1067 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1068 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1070 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1071 D3DFMT_X8R8G8B8, TRUE, 65536, NULL);
1072 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1074 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1075 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1076 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1078 cleanup:
1079 IDirect3D9_Release(d3d);
1080 DestroyWindow(window);
1083 static void test_invalid_multisample(void)
1085 IDirect3DDevice9 *device;
1086 IDirect3DSurface9 *rt;
1087 DWORD quality_levels;
1088 IDirect3D9 *d3d;
1089 BOOL available;
1090 ULONG refcount;
1091 HWND window;
1092 HRESULT hr;
1094 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1095 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1096 ok(!!window, "Failed to create a window.\n");
1097 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1098 ok(!!d3d, "Failed to create a D3D object.\n");
1100 if (!(device = create_device(d3d, window, NULL)))
1102 skip("Failed to create a 3D device, skipping test.\n");
1103 goto cleanup;
1106 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1107 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels));
1108 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1109 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, 0, FALSE, &rt, NULL);
1110 if (available)
1112 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1113 IDirect3DSurface9_Release(rt);
1114 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1115 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, quality_levels, FALSE, &rt, NULL);
1116 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1118 else
1120 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1123 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1124 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels));
1125 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1126 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &rt, NULL);
1127 if (available)
1129 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1130 IDirect3DSurface9_Release(rt);
1131 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1132 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels, FALSE, &rt, NULL);
1133 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1135 else
1137 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1140 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1141 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1142 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1143 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1144 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1145 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, 0, FALSE, &rt, NULL);
1146 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1148 refcount = IDirect3DDevice9_Release(device);
1149 ok(!refcount, "Device has %u references left.\n", refcount);
1150 cleanup:
1151 IDirect3D9_Release(d3d);
1152 DestroyWindow(window);
1155 static void test_swapchain(void)
1157 IDirect3DSwapChain9 *swapchain0;
1158 IDirect3DSwapChain9 *swapchain1;
1159 IDirect3DSwapChain9 *swapchain2;
1160 IDirect3DSwapChain9 *swapchain3;
1161 IDirect3DSwapChain9 *swapchainX;
1162 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1163 D3DPRESENT_PARAMETERS d3dpp;
1164 IDirect3DDevice9 *device;
1165 IDirect3D9 *d3d;
1166 ULONG refcount;
1167 HWND window, window2;
1168 HRESULT hr;
1169 struct device_desc device_desc;
1171 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1172 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1173 ok(!!window, "Failed to create a window.\n");
1174 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1175 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1176 ok(!!window2, "Failed to create a window.\n");
1177 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1178 ok(!!d3d, "Failed to create a D3D object.\n");
1179 if (!(device = create_device(d3d, window, NULL)))
1181 skip("Failed to create a 3D device, skipping test.\n");
1182 goto cleanup;
1185 /* Get the implicit swapchain */
1186 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1187 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1188 /* Check if the back buffer count was modified */
1189 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1190 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1191 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1192 IDirect3DSwapChain9_Release(swapchain0);
1194 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1195 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1196 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1197 backbuffer = (void *)0xdeadbeef;
1198 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1199 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1200 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1201 backbuffer = (void *)0xdeadbeef;
1202 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1203 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1204 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1206 /* Check if there is a back buffer */
1207 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1208 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1209 ok(backbuffer != NULL, "The back buffer is NULL\n");
1210 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1212 /* The back buffer type value is ignored. */
1213 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1214 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1215 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1216 IDirect3DSurface9_Release(stereo_buffer);
1217 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1218 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1219 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1220 IDirect3DSurface9_Release(stereo_buffer);
1221 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1222 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1223 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1224 IDirect3DSurface9_Release(stereo_buffer);
1226 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1227 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1228 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1229 IDirect3DSurface9_Release(stereo_buffer);
1230 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1231 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1232 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1233 IDirect3DSurface9_Release(stereo_buffer);
1234 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1235 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1236 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1237 IDirect3DSurface9_Release(stereo_buffer);
1239 /* Try to get a nonexistent swapchain */
1240 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1241 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1242 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1243 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1245 /* Create a bunch of swapchains */
1246 d3dpp.BackBufferCount = 0;
1247 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1248 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1249 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1251 d3dpp.BackBufferCount = 1;
1252 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1253 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1255 d3dpp.BackBufferCount = 2;
1256 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1257 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1258 if(SUCCEEDED(hr)) {
1259 /* Swapchain 3, created with backbuffercount 2 */
1260 backbuffer = (void *) 0xdeadbeef;
1261 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1262 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1263 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1264 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1266 backbuffer = (void *) 0xdeadbeef;
1267 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1268 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1269 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1270 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1272 backbuffer = (void *) 0xdeadbeef;
1273 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1274 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1275 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1276 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1278 backbuffer = (void *) 0xdeadbeef;
1279 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1280 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1281 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1282 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1285 /* Check the back buffers of the swapchains */
1286 /* Swapchain 1, created with backbuffercount 0 */
1287 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1288 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1289 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1290 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1292 backbuffer = (void *) 0xdeadbeef;
1293 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1294 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1295 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1296 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1298 /* Swapchain 2 - created with backbuffercount 1 */
1299 backbuffer = (void *) 0xdeadbeef;
1300 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1301 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1302 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1303 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1305 backbuffer = (void *) 0xdeadbeef;
1306 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1307 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1308 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1309 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1311 backbuffer = (void *) 0xdeadbeef;
1312 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1313 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1314 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1315 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1317 /* Try getSwapChain on a manually created swapchain
1318 * it should fail, apparently GetSwapChain only returns implicit swapchains
1320 swapchainX = (void *) 0xdeadbeef;
1321 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1322 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1323 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1324 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1326 IDirect3DSwapChain9_Release(swapchain3);
1327 IDirect3DSwapChain9_Release(swapchain2);
1328 IDirect3DSwapChain9_Release(swapchain1);
1330 d3dpp.Windowed = FALSE;
1331 d3dpp.hDeviceWindow = window;
1332 d3dpp.BackBufferCount = 1;
1333 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1334 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1335 d3dpp.hDeviceWindow = window2;
1336 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1337 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1339 device_desc.width = registry_mode.dmPelsWidth;
1340 device_desc.height = registry_mode.dmPelsHeight;
1341 device_desc.device_window = window;
1342 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1343 hr = reset_device(device, &device_desc);
1344 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1346 d3dpp.hDeviceWindow = window;
1347 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1348 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1349 d3dpp.hDeviceWindow = window2;
1350 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1351 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1352 d3dpp.Windowed = TRUE;
1353 d3dpp.hDeviceWindow = window;
1354 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1355 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1356 d3dpp.hDeviceWindow = window2;
1357 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1358 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1360 refcount = IDirect3DDevice9_Release(device);
1361 ok(!refcount, "Device has %u references left.\n", refcount);
1362 cleanup:
1363 IDirect3D9_Release(d3d);
1364 DestroyWindow(window2);
1365 DestroyWindow(window);
1368 static void test_refcount(void)
1370 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1371 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1372 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1373 IDirect3DVertexShader9 *pVertexShader = NULL;
1374 IDirect3DPixelShader9 *pPixelShader = NULL;
1375 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1376 IDirect3DTexture9 *pTexture = NULL;
1377 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1378 IDirect3DVolume9 *pVolumeLevel = NULL;
1379 IDirect3DSurface9 *pStencilSurface = NULL;
1380 IDirect3DSurface9 *pOffscreenSurface = NULL;
1381 IDirect3DSurface9 *pRenderTarget = NULL;
1382 IDirect3DSurface9 *pRenderTarget2 = NULL;
1383 IDirect3DSurface9 *pRenderTarget3 = NULL;
1384 IDirect3DSurface9 *pTextureLevel = NULL;
1385 IDirect3DSurface9 *pBackBuffer = NULL;
1386 IDirect3DStateBlock9 *pStateBlock = NULL;
1387 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1388 IDirect3DSwapChain9 *pSwapChain = NULL;
1389 IDirect3DQuery9 *pQuery = NULL;
1390 D3DPRESENT_PARAMETERS d3dpp;
1391 IDirect3DDevice9 *device;
1392 ULONG refcount = 0, tmp;
1393 IDirect3D9 *d3d, *d3d2;
1394 HWND window;
1395 HRESULT hr;
1397 D3DVERTEXELEMENT9 decl[] =
1399 D3DDECL_END()
1402 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1403 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1404 ok(!!window, "Failed to create a window.\n");
1405 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1406 ok(!!d3d, "Failed to create a D3D object.\n");
1408 CHECK_REFCOUNT(d3d, 1);
1410 if (!(device = create_device(d3d, window, NULL)))
1412 skip("Failed to create a 3D device, skipping test.\n");
1413 goto cleanup;
1416 refcount = get_refcount((IUnknown *)device);
1417 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1419 CHECK_REFCOUNT(d3d, 2);
1421 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1422 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1424 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1425 CHECK_REFCOUNT(d3d, 3);
1426 CHECK_RELEASE_REFCOUNT(d3d, 2);
1429 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1430 * - the container is the device OR swapchain
1431 * - they hold a reference to the device
1432 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1433 * - they are not freed if refcount reaches 0.
1434 * - the refcount is not forwarded to the container.
1436 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1437 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1438 if (pSwapChain)
1440 CHECK_REFCOUNT( pSwapChain, 1);
1442 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1443 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1444 CHECK_REFCOUNT( pSwapChain, 1);
1445 if(pRenderTarget)
1447 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1448 CHECK_REFCOUNT( pRenderTarget, 1);
1450 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1451 CHECK_REFCOUNT(device, refcount);
1452 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1453 CHECK_REFCOUNT(device, refcount);
1455 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1456 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1457 CHECK_REFCOUNT( pRenderTarget, 2);
1458 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
1459 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
1460 CHECK_REFCOUNT(device, --refcount);
1462 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1463 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1464 CHECK_REFCOUNT(device, ++refcount);
1465 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1466 CHECK_REFCOUNT(device, --refcount);
1469 /* Render target and back buffer are identical. */
1470 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1471 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1472 if(pBackBuffer)
1474 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1475 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1476 pRenderTarget, pBackBuffer);
1477 pBackBuffer = NULL;
1479 CHECK_REFCOUNT(device, --refcount);
1481 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1482 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1483 CHECK_REFCOUNT( pSwapChain, 1);
1484 if(pStencilSurface)
1486 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1487 CHECK_REFCOUNT( pStencilSurface, 1);
1489 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1490 CHECK_REFCOUNT(device, refcount);
1491 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1492 CHECK_REFCOUNT(device, refcount);
1494 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
1495 CHECK_REFCOUNT(device, --refcount);
1497 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1498 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1499 CHECK_REFCOUNT(device, ++refcount);
1500 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1501 CHECK_REFCOUNT(device, --refcount);
1502 pStencilSurface = NULL;
1505 CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
1506 CHECK_REFCOUNT(device, --refcount);
1508 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1509 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1510 CHECK_REFCOUNT(device, ++refcount);
1511 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1512 CHECK_REFCOUNT(device, --refcount);
1513 pSwapChain = NULL;
1516 /* Buffers */
1517 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1518 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1519 if(pIndexBuffer)
1521 tmp = get_refcount( (IUnknown *)pIndexBuffer );
1523 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1524 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1525 hr = IDirect3DDevice9_SetIndices(device, NULL);
1526 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1529 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1530 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1531 if(pVertexBuffer)
1533 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1534 UINT offset = ~0;
1535 UINT stride = ~0;
1537 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1539 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1540 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1541 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1542 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1544 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1545 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1546 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1547 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1548 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1550 /* Shaders */
1551 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1552 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1553 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1554 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1555 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1556 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1557 /* Textures */
1558 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1559 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1560 if (pTexture)
1562 tmp = get_refcount( (IUnknown *)pTexture );
1564 /* SetTexture should not increase refcounts */
1565 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1566 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1567 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1568 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1570 /* This should not increment device refcount */
1571 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1572 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1573 /* But should increment texture's refcount */
1574 CHECK_REFCOUNT( pTexture, tmp+1 );
1575 /* Because the texture and surface refcount are identical */
1576 if (pTextureLevel)
1578 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1579 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1580 CHECK_REFCOUNT ( pTexture , tmp+2 );
1581 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1582 CHECK_REFCOUNT ( pTexture , tmp+1 );
1583 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1584 CHECK_REFCOUNT ( pTextureLevel, tmp );
1587 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1588 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1589 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1590 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1591 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1592 if (pVolumeTexture)
1594 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1596 /* This should not increment device refcount */
1597 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1598 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1599 /* But should increment volume texture's refcount */
1600 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1601 /* Because the volume texture and volume refcount are identical */
1602 if (pVolumeLevel)
1604 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1605 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1606 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1607 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1608 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1609 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1610 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1613 /* Surfaces */
1614 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1615 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1616 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1617 CHECK_REFCOUNT( pStencilSurface, 1 );
1618 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1619 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1620 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1621 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1622 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1623 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1624 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1625 CHECK_REFCOUNT( pRenderTarget3, 1 );
1626 /* Misc */
1627 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1628 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1630 memset(&d3dpp, 0, sizeof(d3dpp));
1631 d3dpp.Windowed = TRUE;
1632 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1633 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1634 d3dpp.EnableAutoDepthStencil = TRUE;
1635 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1636 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1637 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1638 if(pSwapChain)
1640 /* check implicit back buffer */
1641 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1642 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1643 CHECK_REFCOUNT( pSwapChain, 1);
1644 if(pBackBuffer)
1646 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1647 CHECK_REFCOUNT( pBackBuffer, 1);
1648 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
1649 CHECK_REFCOUNT(device, --refcount);
1651 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1652 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1653 CHECK_REFCOUNT(device, ++refcount);
1654 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1655 CHECK_REFCOUNT(device, --refcount);
1656 pBackBuffer = NULL;
1658 CHECK_REFCOUNT( pSwapChain, 1);
1660 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1661 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1663 hr = IDirect3DDevice9_BeginStateBlock(device);
1664 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1665 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1666 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1668 /* The implicit render target is not freed if refcount reaches 0.
1669 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1670 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1671 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1672 if(pRenderTarget2)
1674 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1675 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1676 pRenderTarget, pRenderTarget2);
1677 CHECK_REFCOUNT(device, --refcount);
1678 pRenderTarget2 = NULL;
1680 pRenderTarget = NULL;
1682 cleanup:
1683 CHECK_RELEASE(device, device, --refcount);
1685 /* Buffers */
1686 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1687 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1688 /* Shaders */
1689 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1690 CHECK_RELEASE(pVertexShader, device, --refcount);
1691 CHECK_RELEASE(pPixelShader, device, --refcount);
1692 /* Textures */
1693 CHECK_RELEASE(pTextureLevel, device, --refcount);
1694 CHECK_RELEASE(pCubeTexture, device, --refcount);
1695 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1696 /* Surfaces */
1697 CHECK_RELEASE(pStencilSurface, device, --refcount);
1698 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1699 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1700 /* Misc */
1701 CHECK_RELEASE(pStateBlock, device, --refcount);
1702 CHECK_RELEASE(pSwapChain, device, --refcount);
1703 CHECK_RELEASE(pQuery, device, --refcount);
1704 /* This will destroy device - cannot check the refcount here */
1705 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1706 CHECK_RELEASE_REFCOUNT(d3d, 0);
1707 DestroyWindow(window);
1710 static void test_cursor(void)
1712 IDirect3DSurface9 *cursor = NULL;
1713 IDirect3DDevice9 *device;
1714 CURSORINFO info;
1715 IDirect3D9 *d3d;
1716 ULONG refcount;
1717 HCURSOR cur;
1718 HWND window;
1719 HRESULT hr;
1720 BOOL ret;
1722 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1723 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1724 ok(!!window, "Failed to create a window.\n");
1726 ret = SetCursorPos(50, 50);
1727 ok(ret, "Failed to set cursor position.\n");
1728 flush_events();
1729 memset(&info, 0, sizeof(info));
1730 info.cbSize = sizeof(info);
1731 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1732 cur = info.hCursor;
1734 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1735 ok(!!d3d, "Failed to create a D3D object.\n");
1736 if (!(device = create_device(d3d, window, NULL)))
1738 skip("Failed to create a 3D device, skipping test.\n");
1739 goto cleanup;
1742 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1743 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1744 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1746 /* Initially hidden */
1747 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1748 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1750 /* Not enabled without a surface*/
1751 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1752 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1754 /* Fails */
1755 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1756 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1758 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1759 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1761 IDirect3DSurface9_Release(cursor);
1763 memset(&info, 0, sizeof(info));
1764 info.cbSize = sizeof(info);
1765 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1766 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1767 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1769 /* Still hidden */
1770 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1771 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1773 /* Enabled now*/
1774 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1775 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1777 memset(&info, 0, sizeof(info));
1778 info.cbSize = sizeof(info);
1779 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1780 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1781 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1783 refcount = IDirect3DDevice9_Release(device);
1784 ok(!refcount, "Device has %u references left.\n", refcount);
1785 cleanup:
1786 IDirect3D9_Release(d3d);
1787 DestroyWindow(window);
1790 static void test_reset(void)
1792 HRESULT hr;
1793 RECT winrect;
1794 D3DPRESENT_PARAMETERS d3dpp;
1795 D3DDISPLAYMODE d3ddm, d3ddm2;
1796 D3DVIEWPORT9 vp;
1797 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1798 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1799 IDirect3DSurface9 *surface;
1800 IDirect3DTexture9 *texture;
1801 IDirect3DVertexShader9 *shader;
1802 UINT i, adapter_mode_count;
1803 D3DLOCKED_RECT lockrect;
1804 IDirect3DDevice9 *device1 = NULL;
1805 IDirect3DDevice9 *device2 = NULL;
1806 IDirect3DSwapChain9 *swapchain;
1807 struct device_desc device_desc;
1808 DEVMODEW devmode;
1809 IDirect3D9 *d3d;
1810 D3DCAPS9 caps;
1811 DWORD value;
1812 HWND hwnd;
1813 LONG ret;
1814 struct
1816 UINT w;
1817 UINT h;
1818 } *modes = NULL;
1819 UINT mode_count = 0;
1821 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1822 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1823 ok(!!hwnd, "Failed to create a window.\n");
1824 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1825 ok(!!d3d, "Failed to create a D3D object.\n");
1827 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1828 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1829 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1830 for(i = 0; i < adapter_mode_count; ++i)
1832 UINT j;
1833 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1834 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1835 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1837 for (j = 0; j < mode_count; ++j)
1839 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1840 break;
1842 if (j == mode_count)
1844 modes[j].w = d3ddm2.Width;
1845 modes[j].h = d3ddm2.Height;
1846 ++mode_count;
1849 /* We use them as invalid modes */
1850 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1851 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1852 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1853 d3ddm2.Width, d3ddm2.Height);
1854 goto cleanup;
1858 if (mode_count < 2)
1860 skip("Less than 2 modes supported, skipping mode tests\n");
1861 goto cleanup;
1864 i = 0;
1865 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1867 device_desc.width = modes[i].w;
1868 device_desc.height = modes[i].h;
1869 device_desc.device_window = hwnd;
1870 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1871 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1873 skip("Failed to create a D3D device, skipping tests.\n");
1874 goto cleanup;
1876 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1877 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1879 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1880 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1882 width = GetSystemMetrics(SM_CXSCREEN);
1883 height = GetSystemMetrics(SM_CYSCREEN);
1884 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1885 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1887 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1888 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1889 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1890 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1891 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1892 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1893 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1894 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1896 i = 1;
1897 vp.X = 10;
1898 vp.Y = 20;
1899 vp.MinZ = 2;
1900 vp.MaxZ = 3;
1901 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1902 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1904 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1905 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1906 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1907 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1908 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1910 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1911 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1912 d3dpp.Windowed = FALSE;
1913 d3dpp.BackBufferWidth = modes[i].w;
1914 d3dpp.BackBufferHeight = modes[i].h;
1915 d3dpp.BackBufferFormat = d3ddm.Format;
1916 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1917 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1918 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1919 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1921 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1922 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1923 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1925 ZeroMemory(&vp, sizeof(vp));
1926 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1927 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1928 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1929 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1930 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1931 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1932 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1933 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1935 width = GetSystemMetrics(SM_CXSCREEN);
1936 height = GetSystemMetrics(SM_CYSCREEN);
1937 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1938 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1940 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1941 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1942 memset(&d3dpp, 0, sizeof(d3dpp));
1943 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1944 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1945 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1946 d3dpp.BackBufferWidth, modes[i].w);
1947 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1948 d3dpp.BackBufferHeight, modes[i].h);
1949 IDirect3DSwapChain9_Release(swapchain);
1951 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1952 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1953 d3dpp.Windowed = TRUE;
1954 d3dpp.BackBufferWidth = 400;
1955 d3dpp.BackBufferHeight = 300;
1956 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1957 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1958 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1959 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1960 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1962 width = GetSystemMetrics(SM_CXSCREEN);
1963 height = GetSystemMetrics(SM_CYSCREEN);
1964 ok(width == orig_width, "Screen width is %d\n", width);
1965 ok(height == orig_height, "Screen height is %d\n", height);
1967 ZeroMemory(&vp, sizeof(vp));
1968 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1969 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1970 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1971 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1972 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1973 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1974 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1975 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1977 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1978 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1979 memset(&d3dpp, 0, sizeof(d3dpp));
1980 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1981 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1982 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1983 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1984 IDirect3DSwapChain9_Release(swapchain);
1986 memset(&devmode, 0, sizeof(devmode));
1987 devmode.dmSize = sizeof(devmode);
1988 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1989 devmode.dmPelsWidth = modes[1].w;
1990 devmode.dmPelsHeight = modes[1].h;
1991 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1992 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1993 width = GetSystemMetrics(SM_CXSCREEN);
1994 height = GetSystemMetrics(SM_CYSCREEN);
1995 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1996 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1998 d3dpp.BackBufferWidth = 500;
1999 d3dpp.BackBufferHeight = 400;
2000 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
2001 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2002 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed, hr %#x.\n", hr);
2003 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2004 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x.\n", hr);
2006 width = GetSystemMetrics(SM_CXSCREEN);
2007 height = GetSystemMetrics(SM_CYSCREEN);
2008 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2009 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2011 ZeroMemory(&vp, sizeof(vp));
2012 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2013 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed, hr %#x.\n", hr);
2014 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
2015 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
2016 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
2017 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
2018 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
2019 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
2021 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2022 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2023 memset(&d3dpp, 0, sizeof(d3dpp));
2024 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2025 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2026 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2027 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2028 IDirect3DSwapChain9_Release(swapchain);
2030 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2031 devmode.dmPelsWidth = orig_width;
2032 devmode.dmPelsHeight = orig_height;
2033 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2034 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2035 width = GetSystemMetrics(SM_CXSCREEN);
2036 height = GetSystemMetrics(SM_CYSCREEN);
2037 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
2038 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
2040 SetRect(&winrect, 0, 0, 200, 150);
2041 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
2042 ok(SetWindowPos(hwnd, NULL, 0, 0,
2043 winrect.right-winrect.left,
2044 winrect.bottom-winrect.top,
2045 SWP_NOMOVE|SWP_NOZORDER),
2046 "SetWindowPos failed\n");
2048 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2049 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2050 d3dpp.Windowed = TRUE;
2051 d3dpp.BackBufferWidth = 0;
2052 d3dpp.BackBufferHeight = 0;
2053 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
2054 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2055 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2056 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2057 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2059 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2060 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2061 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2062 d3dpp.BackBufferFormat, d3ddm.Format);
2063 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2064 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2065 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2066 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2067 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
2068 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2069 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2070 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2071 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2072 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2073 d3dpp.FullScreen_RefreshRateInHz);
2074 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2076 ZeroMemory(&vp, sizeof(vp));
2077 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2078 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
2079 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
2080 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
2081 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
2082 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
2083 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2084 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2086 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2087 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2088 memset(&d3dpp, 0, sizeof(d3dpp));
2089 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2090 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2091 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2092 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2093 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2094 d3dpp.BackBufferFormat, d3ddm.Format);
2095 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2096 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2097 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2098 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2099 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
2100 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2101 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2102 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2103 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2104 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2105 d3dpp.FullScreen_RefreshRateInHz);
2106 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2107 IDirect3DSwapChain9_Release(swapchain);
2109 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2110 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2111 d3dpp.Windowed = TRUE;
2112 d3dpp.BackBufferWidth = 400;
2113 d3dpp.BackBufferHeight = 300;
2115 /* _Reset fails if there is a resource in the default pool */
2116 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
2117 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2118 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2119 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2120 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2121 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2122 IDirect3DSurface9_Release(surface);
2123 /* Reset again to get the device out of the lost state */
2124 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2125 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2126 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2127 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2129 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
2131 IDirect3DVolumeTexture9 *volume_texture;
2133 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
2134 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
2135 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
2136 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2137 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2138 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2139 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
2140 hr, D3DERR_DEVICENOTRESET);
2141 IDirect3DVolumeTexture9_Release(volume_texture);
2142 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2143 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
2144 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2145 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2147 else
2149 skip("Volume textures not supported.\n");
2152 /* Scratch, sysmem and managed pools are fine */
2153 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2154 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2155 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2156 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2157 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2158 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2159 IDirect3DSurface9_Release(surface);
2161 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2162 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2163 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2164 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2165 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2166 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2167 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2168 IDirect3DSurface9_Release(surface);
2170 /* The depth stencil should get reset to the auto depth stencil when present. */
2171 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2172 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2174 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2175 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2176 ok(surface == NULL, "Depth stencil should be NULL\n");
2178 d3dpp.EnableAutoDepthStencil = TRUE;
2179 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2180 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2181 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2183 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2184 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2185 ok(surface != NULL, "Depth stencil should not be NULL\n");
2186 if (surface) IDirect3DSurface9_Release(surface);
2188 d3dpp.EnableAutoDepthStencil = FALSE;
2189 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2190 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2192 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2193 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2194 ok(surface == NULL, "Depth stencil should be NULL\n");
2196 /* Will a sysmem or scratch survive while locked */
2197 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2198 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2199 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2200 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2201 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2202 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2203 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2204 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2205 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2206 IDirect3DSurface9_UnlockRect(surface);
2207 IDirect3DSurface9_Release(surface);
2209 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2210 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2211 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2212 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2213 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2214 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2215 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2216 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2217 IDirect3DSurface9_UnlockRect(surface);
2218 IDirect3DSurface9_Release(surface);
2220 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2221 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2222 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2223 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2224 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2225 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2226 IDirect3DTexture9_Release(texture);
2228 /* A reference held to an implicit surface causes failures as well */
2229 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2230 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2231 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2232 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2233 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2234 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2235 IDirect3DSurface9_Release(surface);
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);
2241 /* Shaders are fine as well */
2242 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2243 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2244 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2245 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2246 IDirect3DVertexShader9_Release(shader);
2248 /* Try setting invalid modes */
2249 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2250 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2251 d3dpp.Windowed = FALSE;
2252 d3dpp.BackBufferWidth = 32;
2253 d3dpp.BackBufferHeight = 32;
2254 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2255 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2256 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2257 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2259 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2260 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2261 d3dpp.Windowed = FALSE;
2262 d3dpp.BackBufferWidth = 801;
2263 d3dpp.BackBufferHeight = 600;
2264 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2265 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2266 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2267 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2269 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2270 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2271 d3dpp.Windowed = FALSE;
2272 d3dpp.BackBufferWidth = 0;
2273 d3dpp.BackBufferHeight = 0;
2274 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2275 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2276 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2277 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2279 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2281 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2282 d3dpp.Windowed = TRUE;
2283 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2284 d3dpp.BackBufferFormat = d3ddm.Format;
2285 d3dpp.EnableAutoDepthStencil = FALSE;
2286 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2288 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2289 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2291 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2292 goto cleanup;
2295 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2296 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2298 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2299 d3dpp.Windowed = TRUE;
2300 d3dpp.BackBufferWidth = 400;
2301 d3dpp.BackBufferHeight = 300;
2302 d3dpp.EnableAutoDepthStencil = TRUE;
2303 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2305 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2306 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2308 if (FAILED(hr)) goto cleanup;
2310 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2311 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2312 ok(surface != NULL, "Depth stencil should not be NULL\n");
2313 if (surface) IDirect3DSurface9_Release(surface);
2315 cleanup:
2316 HeapFree(GetProcessHeap(), 0, modes);
2317 if (device2)
2319 UINT refcount = IDirect3DDevice9_Release(device2);
2320 ok(!refcount, "Device has %u references left.\n", refcount);
2322 if (device1)
2324 UINT refcount = IDirect3DDevice9_Release(device1);
2325 ok(!refcount, "Device has %u references left.\n", refcount);
2327 IDirect3D9_Release(d3d);
2328 DestroyWindow(hwnd);
2331 /* Test adapter display modes */
2332 static void test_display_modes(void)
2334 D3DDISPLAYMODE dmode;
2335 IDirect3D9 *d3d;
2337 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2338 ok(!!d3d, "Failed to create a D3D object.\n");
2340 #define TEST_FMT(x,r) do { \
2341 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2342 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2343 } while(0)
2345 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2346 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2347 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2348 /* D3DFMT_R5G6B5 */
2349 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2350 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2351 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2352 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2353 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2354 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2355 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2356 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2357 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2358 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2359 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2360 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2362 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2363 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2365 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2366 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2367 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2369 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2370 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2371 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2372 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2373 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2374 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2376 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2377 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2378 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2379 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2380 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2381 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2382 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2383 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2384 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2385 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2387 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2388 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2389 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2390 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2391 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2392 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2393 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2394 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2395 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2396 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2398 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2399 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2400 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2401 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2402 /* Floating point formats */
2403 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2404 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2405 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2407 /* IEEE formats */
2408 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2409 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2410 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2412 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2414 TEST_FMT(0, D3DERR_INVALIDCALL);
2416 IDirect3D9_Release(d3d);
2419 static void test_scene(void)
2421 IDirect3DSurface9 *surface1, *surface2, *surface3;
2422 IDirect3DSurface9 *backBuffer, *rt, *ds;
2423 RECT rect = {0, 0, 128, 128};
2424 IDirect3DDevice9 *device;
2425 IDirect3D9 *d3d;
2426 ULONG refcount;
2427 D3DCAPS9 caps;
2428 HWND window;
2429 HRESULT hr;
2431 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2432 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2433 ok(!!window, "Failed to create a window.\n");
2434 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2435 ok(!!d3d, "Failed to create a D3D object.\n");
2436 if (!(device = create_device(d3d, window, NULL)))
2438 skip("Failed to create a 3D device, skipping test.\n");
2439 goto cleanup;
2442 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2443 memset(&caps, 0, sizeof(caps));
2444 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2445 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2447 /* Test an EndScene without BeginScene. Should return an error */
2448 hr = IDirect3DDevice9_EndScene(device);
2449 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2451 /* Test a normal BeginScene / EndScene pair, this should work */
2452 hr = IDirect3DDevice9_BeginScene(device);
2453 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2454 hr = IDirect3DDevice9_EndScene(device);
2455 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2457 /* Test another EndScene without having begun a new scene. Should return an error */
2458 hr = IDirect3DDevice9_EndScene(device);
2459 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2461 /* Two nested BeginScene and EndScene calls */
2462 hr = IDirect3DDevice9_BeginScene(device);
2463 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2464 hr = IDirect3DDevice9_BeginScene(device);
2465 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2466 hr = IDirect3DDevice9_EndScene(device);
2467 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2468 hr = IDirect3DDevice9_EndScene(device);
2469 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2471 /* Create some surfaces to test stretchrect between the scenes */
2472 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2473 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2474 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2475 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2476 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2477 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2478 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2479 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2480 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2481 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2482 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2483 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2485 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2486 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2487 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2488 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2490 /* First make sure a simple StretchRect call works */
2491 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2492 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2493 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2494 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2495 if (0) /* Disabled for now because it crashes in wine */
2497 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2498 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2499 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2502 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2503 * BeginScene - Endscene pair with normal surfaces and render targets, but
2504 * not depth stencil surfaces. */
2505 hr = IDirect3DDevice9_BeginScene(device);
2506 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2508 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2509 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2510 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2511 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2512 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2513 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2514 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2516 hr = IDirect3DDevice9_EndScene(device);
2517 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2519 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2520 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2521 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2523 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2524 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2525 hr = IDirect3DDevice9_BeginScene(device);
2526 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2527 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2528 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2529 hr = IDirect3DDevice9_EndScene(device);
2530 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2532 IDirect3DSurface9_Release(rt);
2533 IDirect3DSurface9_Release(ds);
2534 IDirect3DSurface9_Release(backBuffer);
2535 IDirect3DSurface9_Release(surface1);
2536 IDirect3DSurface9_Release(surface2);
2537 IDirect3DSurface9_Release(surface3);
2538 refcount = IDirect3DDevice9_Release(device);
2539 ok(!refcount, "Device has %u references left.\n", refcount);
2540 cleanup:
2541 IDirect3D9_Release(d3d);
2542 DestroyWindow(window);
2545 static void test_limits(void)
2547 IDirect3DTexture9 *texture;
2548 IDirect3DDevice9 *device;
2549 IDirect3D9 *d3d;
2550 unsigned int i;
2551 ULONG refcount;
2552 HWND window;
2553 HRESULT hr;
2555 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2556 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2557 ok(!!window, "Failed to create a window.\n");
2558 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2559 ok(!!d3d, "Failed to create a D3D object.\n");
2560 if (!(device = create_device(d3d, window, NULL)))
2562 skip("Failed to create a 3D device, skipping test.\n");
2563 goto cleanup;
2566 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2567 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2569 /* There are 16 pixel samplers. We should be able to access all of them */
2570 for (i = 0; i < 16; ++i)
2572 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2573 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2574 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2575 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2576 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2577 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2580 /* Now test all 8 textures stage states */
2581 for (i = 0; i < 8; ++i)
2583 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2584 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2587 /* Investigations show that accessing higher samplers / textures stage
2588 * states does not return an error either. Writing to too high samplers
2589 * (approximately sampler 40) causes memory corruption in Windows, so
2590 * there is no bounds checking. */
2591 IDirect3DTexture9_Release(texture);
2592 refcount = IDirect3D9_Release(device);
2593 ok(!refcount, "Device has %u references left.\n", refcount);
2594 cleanup:
2595 IDirect3D9_Release(d3d);
2596 DestroyWindow(window);
2599 static void test_depthstenciltest(void)
2601 HRESULT hr;
2602 IDirect3DDevice9 *pDevice = NULL;
2603 D3DPRESENT_PARAMETERS d3dpp;
2604 D3DDISPLAYMODE d3ddm;
2605 IDirect3DSurface9 *pDepthStencil = NULL;
2606 IDirect3DSurface9 *pDepthStencil2 = NULL;
2607 IDirect3D9 *d3d;
2608 DWORD state;
2609 HWND hwnd;
2611 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2612 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2613 ok(!!hwnd, "Failed to create a window.\n");
2614 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2615 ok(!!d3d, "Failed to create a D3D object.\n");
2617 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2618 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2619 d3dpp.Windowed = TRUE;
2620 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2621 d3dpp.BackBufferWidth = 800;
2622 d3dpp.BackBufferHeight = 600;
2623 d3dpp.BackBufferFormat = d3ddm.Format;
2624 d3dpp.EnableAutoDepthStencil = TRUE;
2625 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2627 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2628 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2629 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2630 if(!pDevice)
2632 skip("Failed to create a d3d device\n");
2633 goto cleanup;
2636 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2637 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2639 /* Try to clear */
2640 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2641 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2643 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2644 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2646 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2647 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2648 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2649 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2651 /* This left the render states untouched! */
2652 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2653 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2654 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2655 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2656 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2657 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2658 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2659 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2660 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2661 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2662 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2663 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2665 /* This is supposed to fail now */
2666 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2667 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2669 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2670 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2672 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2673 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2675 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2676 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2677 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2679 /* Now it works again */
2680 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2681 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2683 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2684 if(pDevice) IDirect3D9_Release(pDevice);
2686 /* Now see if autodepthstencil disable is honored. First, without a format set */
2687 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2688 d3dpp.Windowed = TRUE;
2689 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2690 d3dpp.BackBufferWidth = 800;
2691 d3dpp.BackBufferHeight = 600;
2692 d3dpp.BackBufferFormat = d3ddm.Format;
2693 d3dpp.EnableAutoDepthStencil = FALSE;
2694 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2696 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2697 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2698 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2699 if(!pDevice)
2701 skip("Failed to create a d3d device\n");
2702 goto cleanup;
2705 pDepthStencil = NULL;
2706 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2707 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2708 if(pDepthStencil) {
2709 IDirect3DSurface9_Release(pDepthStencil);
2710 pDepthStencil = NULL;
2713 /* Check the depth test state */
2714 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2715 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2716 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2718 if(pDevice) IDirect3D9_Release(pDevice);
2720 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil 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_D16;
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 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2748 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2749 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2751 cleanup:
2752 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2753 if (pDevice)
2755 UINT refcount = IDirect3D9_Release(pDevice);
2756 ok(!refcount, "Device has %u references left.\n", refcount);
2758 IDirect3D9_Release(d3d);
2759 DestroyWindow(hwnd);
2762 static void test_get_rt(void)
2764 IDirect3DSurface9 *backbuffer, *rt;
2765 IDirect3DDevice9 *device;
2766 IDirect3D9 *d3d9;
2767 D3DCAPS9 caps;
2768 HWND window;
2769 HRESULT hr;
2770 ULONG ref;
2771 UINT i;
2773 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2774 0, 0, 128, 128, 0, 0, 0, 0);
2775 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2776 ok(!!d3d9, "Failed to create a D3D object.\n");
2777 device = create_device(d3d9, window, NULL);
2778 if (!device)
2780 skip("Failed to create a D3D device, skipping tests.\n");
2781 goto done;
2784 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2785 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2786 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2788 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2789 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2791 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2793 rt = backbuffer;
2794 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2795 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2796 ok(!rt, "Got rt %p.\n", rt);
2799 IDirect3DSurface9_Release(backbuffer);
2801 ref = IDirect3DDevice9_Release(device);
2802 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2803 done:
2804 IDirect3D9_Release(d3d9);
2805 DestroyWindow(window);
2808 static void test_draw_primitive(void)
2810 static const struct
2812 float position[3];
2813 DWORD color;
2815 quad[] =
2817 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2818 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2819 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2820 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2822 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
2823 static const D3DVERTEXELEMENT9 decl_elements[] =
2825 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2826 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2827 D3DDECL_END()
2830 IDirect3DVertexDeclaration9 *vertex_declaration;
2831 IDirect3DVertexBuffer9 *vertex_buffer;
2832 IDirect3DIndexBuffer9 *index_buffer;
2833 IDirect3DDevice9 *device;
2834 IDirect3D9 *d3d9;
2835 ULONG refcount;
2836 HWND window;
2837 HRESULT hr;
2838 void *ptr;
2840 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
2841 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2842 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2843 ok(!!d3d9, "Failed to create a D3D object.\n");
2844 if (!(device = create_device(d3d9, window, NULL)))
2846 skip("Failed to create a D3D device.\n");
2847 IDirect3D9_Release(d3d9);
2848 DestroyWindow(window);
2849 return;
2852 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2853 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
2855 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
2856 D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2857 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#x.\n", hr);
2858 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2859 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2860 memcpy(ptr, quad, sizeof(quad));
2861 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2862 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2863 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2864 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#x.\n", hr);
2866 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
2867 D3DPOOL_DEFAULT, &index_buffer, NULL);
2868 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#x.\n", hr);
2869 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2870 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2871 memcpy(ptr, indices, sizeof(indices));
2872 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2873 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2875 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2876 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#x.\n", hr);
2878 hr = IDirect3DDevice9_BeginScene(device);
2879 ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2881 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2882 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2884 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2885 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2887 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2888 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2890 hr = IDirect3DDevice9_SetIndices(device, NULL);
2891 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2892 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2893 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2894 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2896 /* Valid index buffer, NULL vertex declaration. Should fail */
2897 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2898 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2899 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2900 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2901 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2903 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2904 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2905 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2907 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2908 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2910 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2911 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2913 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2914 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2916 /* NULL index buffer, valid vertex vertex declaration. Should succeed */
2917 hr = IDirect3DDevice9_SetIndices(device, NULL);
2918 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2919 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2920 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2921 todo_wine ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2923 /* Valid index buffer and vertex declaration. Should succeed */
2924 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
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(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2930 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2931 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2932 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#x.\n", hr);
2934 hr = IDirect3DDevice9_EndScene(device);
2935 ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2937 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2938 ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2940 IDirect3DVertexBuffer9_Release(vertex_buffer);
2941 IDirect3DIndexBuffer9_Release(index_buffer);
2942 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2943 refcount = IDirect3DDevice9_Release(device);
2944 ok(!refcount, "Device has %u references left.\n", refcount);
2945 IDirect3D9_Release(d3d9);
2946 DestroyWindow(window);
2949 static void test_null_stream(void)
2951 IDirect3DVertexBuffer9 *buffer = NULL;
2952 IDirect3DDevice9 *device;
2953 IDirect3D9 *d3d9;
2954 ULONG refcount;
2955 HWND window;
2956 HRESULT hr;
2957 IDirect3DVertexShader9 *shader = NULL;
2958 IDirect3DVertexDeclaration9 *decl = NULL;
2959 static const DWORD shader_code[] =
2961 0xfffe0101, /* vs_1_1 */
2962 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2963 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2964 0x0000ffff /* end */
2966 static const D3DVERTEXELEMENT9 decl_elements[] = {
2967 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2968 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2969 D3DDECL_END()
2972 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2973 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2974 ok(!!window, "Failed to create a window.\n");
2975 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2976 ok(!!d3d9, "Failed to create a D3D object.\n");
2977 if (!(device = create_device(d3d9, window, NULL)))
2979 skip("Failed to create a 3D device, skipping test.\n");
2980 goto cleanup;
2983 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2984 if(FAILED(hr)) {
2985 skip("No vertex shader support\n");
2986 goto cleanup;
2988 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2989 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2990 if (FAILED(hr)) {
2991 skip("Vertex declaration handling not possible.\n");
2992 goto cleanup;
2994 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2995 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2996 if (FAILED(hr)) {
2997 skip("Vertex buffer handling not possible.\n");
2998 goto cleanup;
3001 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
3002 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3003 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
3004 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3005 hr = IDirect3DDevice9_SetVertexShader(device, shader);
3006 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
3007 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3008 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
3010 hr = IDirect3DDevice9_BeginScene(device);
3011 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3012 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
3013 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3014 hr = IDirect3DDevice9_EndScene(device);
3015 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3017 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3018 IDirect3DDevice9_SetVertexShader(device, NULL);
3019 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3021 cleanup:
3022 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
3023 if (decl) IDirect3DVertexDeclaration9_Release(decl);
3024 if (shader) IDirect3DVertexShader9_Release(shader);
3025 if (device)
3027 refcount = IDirect3DDevice9_Release(device);
3028 ok(!refcount, "Device has %u references left.\n", refcount);
3030 IDirect3D9_Release(d3d9);
3031 DestroyWindow(window);
3034 static void test_lights(void)
3036 IDirect3DDevice9 *device;
3037 IDirect3D9 *d3d9;
3038 ULONG refcount;
3039 HWND window;
3040 HRESULT hr;
3041 unsigned int i;
3042 BOOL enabled;
3043 D3DCAPS9 caps;
3045 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3046 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3047 ok(!!window, "Failed to create a window.\n");
3048 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3049 ok(!!d3d9, "Failed to create a D3D object.\n");
3050 if (!(device = create_device(d3d9, window, NULL)))
3052 skip("Failed to create a 3D device, skipping test.\n");
3053 goto cleanup;
3056 memset(&caps, 0, sizeof(caps));
3057 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3058 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
3060 for(i = 1; i <= caps.MaxActiveLights; i++) {
3061 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
3062 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
3063 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
3064 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
3065 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
3068 /* TODO: Test the rendering results in this situation */
3069 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
3070 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
3071 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
3072 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
3073 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
3074 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
3075 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
3077 for(i = 1; i <= caps.MaxActiveLights; i++) {
3078 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
3079 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
3082 refcount = IDirect3DDevice9_Release(device);
3083 ok(!refcount, "Device has %u references left.\n", refcount);
3084 cleanup:
3085 IDirect3D9_Release(d3d9);
3086 DestroyWindow(window);
3089 static void test_set_stream_source(void)
3091 IDirect3DVertexBuffer9 *vb;
3092 IDirect3DDevice9 *device;
3093 IDirect3D9 *d3d9;
3094 ULONG refcount;
3095 HWND window;
3096 HRESULT hr;
3098 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3099 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3100 ok(!!window, "Failed to create a window.\n");
3101 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3102 ok(!!d3d9, "Failed to create a D3D object.\n");
3103 if (!(device = create_device(d3d9, window, NULL)))
3105 skip("Failed to create a 3D device, skipping test.\n");
3106 goto cleanup;
3109 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
3110 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
3112 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
3113 * (Radeon 9000 verified) reject them, so accept both results. Wine
3114 * currently rejects this to be able to optimize the vbo conversion, but
3115 * writes a WARN. */
3116 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
3117 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3118 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
3119 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3120 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
3121 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3122 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
3123 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3124 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
3125 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3127 /* Try to set the NULL buffer with an offset and stride 0 */
3128 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3129 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3130 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
3131 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3132 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
3133 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3134 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
3135 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3136 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
3137 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3139 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3140 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3142 IDirect3DVertexBuffer9_Release(vb);
3143 refcount = IDirect3DDevice9_Release(device);
3144 ok(!refcount, "Device has %u references left.\n", refcount);
3145 cleanup:
3146 IDirect3D9_Release(d3d9);
3147 DestroyWindow(window);
3150 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
3151 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
3152 * a fixed number of combinations are possible in fullscreen mode. In windowed
3153 * mode more combinations are allowed due to format conversion and this is
3154 * likely driver dependent. */
3155 static void test_display_formats(void)
3157 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
3158 unsigned int backbuffer, display;
3159 unsigned int windowed;
3160 IDirect3D9 *d3d9;
3161 BOOL should_pass;
3162 BOOL has_modes;
3163 HRESULT hr;
3165 static const struct
3167 const char *name;
3168 D3DFORMAT format;
3169 D3DFORMAT alpha_format;
3170 BOOL display;
3171 BOOL windowed;
3173 formats[] =
3175 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
3176 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
3177 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
3178 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
3179 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3180 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3181 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3184 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3185 ok(!!d3d9, "Failed to create a D3D object.\n");
3187 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
3189 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3191 for (windowed = 0; windowed <= 1; ++windowed)
3193 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
3195 should_pass = FALSE;
3197 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3199 D3DFORMAT backbuffer_format;
3201 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3202 backbuffer_format = formats[display].format;
3203 else
3204 backbuffer_format = formats[backbuffer].format;
3206 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3207 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3208 if (hr == D3D_OK)
3210 if (windowed)
3212 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3213 backbuffer_format, formats[display].format);
3214 should_pass = (hr == D3D_OK);
3216 else
3217 should_pass = (formats[display].format == formats[backbuffer].format
3218 || (formats[display].alpha_format
3219 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3223 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3224 formats[display].format, formats[backbuffer].format, windowed);
3225 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3226 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3227 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3232 IDirect3D9_Release(d3d9);
3235 static void test_scissor_size(void)
3237 struct device_desc device_desc;
3238 IDirect3D9 *d3d9_ptr;
3239 unsigned int i;
3240 static struct {
3241 int winx; int winy; int backx; int backy; DWORD flags;
3242 } scts[] = { /* scissor tests */
3243 {800, 600, 640, 480, 0},
3244 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3245 {640, 480, 800, 600, 0},
3246 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3249 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3250 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3252 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
3253 IDirect3DDevice9 *device_ptr = 0;
3254 HRESULT hr;
3255 HWND hwnd = 0;
3256 RECT scissorrect;
3258 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3259 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3261 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3263 scts[i].backx = registry_mode.dmPelsWidth;
3264 scts[i].backy = registry_mode.dmPelsHeight;
3267 device_desc.device_window = hwnd;
3268 device_desc.width = scts[i].backx;
3269 device_desc.height = scts[i].backy;
3270 device_desc.flags = scts[i].flags;
3271 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3273 skip("Failed to create a 3D device, skipping test.\n");
3274 DestroyWindow(hwnd);
3275 goto err_out;
3278 /* Check for the default scissor rect size */
3279 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3280 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3281 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3282 && scissorrect.top == 0 && scissorrect.left == 0,
3283 "Scissorrect mismatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3284 scts[i].backx, scts[i].backy);
3286 /* check the scissorrect values after a reset */
3287 device_desc.width = registry_mode.dmPelsWidth;
3288 device_desc.height = registry_mode.dmPelsHeight;
3289 device_desc.flags = scts[i].flags;
3290 hr = reset_device(device_ptr, &device_desc);
3291 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3292 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3293 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3295 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3296 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3297 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3298 && scissorrect.top == 0 && scissorrect.left == 0,
3299 "Scissorrect mismatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3300 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3302 if(device_ptr) {
3303 ULONG ref;
3305 ref = IDirect3DDevice9_Release(device_ptr);
3306 DestroyWindow(hwnd);
3307 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3311 err_out:
3312 IDirect3D9_Release(d3d9_ptr);
3315 static void test_multi_device(void)
3317 IDirect3DDevice9 *device1, *device2;
3318 HWND window1, window2;
3319 IDirect3D9 *d3d9;
3320 ULONG refcount;
3322 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3323 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3324 ok(!!window1, "Failed to create a window.\n");
3325 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3326 ok(!!d3d9, "Failed to create a D3D object.\n");
3327 if (!(device1 = create_device(d3d9, window1, NULL)))
3329 skip("Failed to create a 3D device, skipping test.\n");
3330 IDirect3D9_Release(d3d9);
3331 DestroyWindow(window1);
3332 return;
3334 IDirect3D9_Release(d3d9);
3336 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3337 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3338 ok(!!window2, "Failed to create a window.\n");
3339 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3340 ok(!!d3d9, "Failed to create a D3D object.\n");
3341 device2 = create_device(d3d9, window2, NULL);
3342 IDirect3D9_Release(d3d9);
3344 refcount = IDirect3DDevice9_Release(device2);
3345 ok(!refcount, "Device has %u references left.\n", refcount);
3346 refcount = IDirect3DDevice9_Release(device1);
3347 ok(!refcount, "Device has %u references left.\n", refcount);
3348 DestroyWindow(window2);
3349 DestroyWindow(window1);
3352 static HWND filter_messages;
3354 enum message_window
3356 DEVICE_WINDOW,
3357 FOCUS_WINDOW,
3360 struct message
3362 UINT message;
3363 enum message_window window;
3364 BOOL check_wparam;
3365 WPARAM expect_wparam;
3368 static const struct message *expect_messages;
3369 static HWND device_window, focus_window;
3370 static LONG windowposchanged_received, syscommand_received;
3372 struct wndproc_thread_param
3374 HWND dummy_window;
3375 HANDLE window_created;
3376 HANDLE test_finished;
3377 BOOL running_in_foreground;
3380 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3382 if (filter_messages && filter_messages == hwnd)
3384 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3385 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3388 if (expect_messages)
3390 HWND w;
3392 switch (expect_messages->window)
3394 case DEVICE_WINDOW:
3395 w = device_window;
3396 break;
3398 case FOCUS_WINDOW:
3399 w = focus_window;
3400 break;
3402 default:
3403 w = NULL;
3404 break;
3407 if (hwnd == w && expect_messages->message == message)
3409 if (expect_messages->check_wparam)
3410 ok(wparam == expect_messages->expect_wparam,
3411 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3412 wparam, message, expect_messages->expect_wparam);
3414 ++expect_messages;
3418 /* KDE randomly does something with the hidden window during the
3419 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3420 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3421 * just flag WM_WINDOWPOSCHANGED as bad. */
3422 if (message == WM_WINDOWPOSCHANGED)
3423 InterlockedIncrement(&windowposchanged_received);
3424 else if (message == WM_SYSCOMMAND)
3425 InterlockedIncrement(&syscommand_received);
3427 return DefWindowProcA(hwnd, message, wparam, lparam);
3430 static DWORD WINAPI wndproc_thread(void *param)
3432 struct wndproc_thread_param *p = param;
3433 DWORD res;
3434 BOOL ret;
3436 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3437 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3438 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3439 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3441 ret = SetEvent(p->window_created);
3442 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3444 for (;;)
3446 MSG msg;
3448 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3449 res = WaitForSingleObject(p->test_finished, 100);
3450 if (res == WAIT_OBJECT_0) break;
3451 if (res != WAIT_TIMEOUT)
3453 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3454 break;
3458 DestroyWindow(p->dummy_window);
3460 return 0;
3463 static void test_wndproc(void)
3465 struct wndproc_thread_param thread_params;
3466 struct device_desc device_desc;
3467 IDirect3DDevice9 *device;
3468 WNDCLASSA wc = {0};
3469 IDirect3D9 *d3d9;
3470 HANDLE thread;
3471 LONG_PTR proc;
3472 ULONG ref;
3473 DWORD res, tid;
3474 HWND tmp;
3475 UINT i, adapter_mode_count;
3476 HRESULT hr;
3477 D3DDISPLAYMODE d3ddm;
3478 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3479 DEVMODEW devmode;
3480 LONG change_ret;
3481 BOOL ret;
3483 static const struct message create_messages[] =
3485 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3486 /* Do not test wparam here. If device creation succeeds,
3487 * wparam is WA_ACTIVE. If device creation fails (testbot)
3488 * wparam is set to WA_INACTIVE on some Windows versions. */
3489 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3490 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3491 {0, 0, FALSE, 0},
3493 static const struct message focus_loss_messages[] =
3495 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3496 * not reliable on X11 WMs. When the window focus follows the
3497 * mouse pointer the message is not sent.
3498 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3499 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3500 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3501 * not deterministic. */
3502 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3503 /* Windows sends WM_ACTIVATE to the device window, indicating that
3504 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3505 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3506 * leaves the device window active, breaking re-activation in the
3507 * lost device test.
3508 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3509 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3510 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3511 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3512 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3513 * not deterministic. It may be sent after the focus window handling
3514 * or before. */
3515 {0, 0, FALSE, 0},
3517 static const struct message focus_loss_messages_nowc[] =
3519 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3520 * not reliable on X11 WMs. When the window focus follows the
3521 * mouse pointer the message is not sent.
3522 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3523 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3524 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3525 {0, 0, FALSE, 0},
3527 static const struct message reactivate_messages[] =
3529 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3530 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3531 /* optional WM_MOVE here if size changed */
3532 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3533 {0, 0, FALSE, 0},
3535 static const struct message reactivate_messages_nowc[] =
3537 /* We're activating the device window before activating the
3538 * focus window, so no ACTIVATEAPP message is sent. */
3539 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3540 {0, 0, FALSE, 0},
3542 static const struct message focus_loss_messages_hidden[] =
3544 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3545 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3546 {0, 0, FALSE, 0},
3548 static const struct message focus_loss_messages_filtered[] =
3550 /* WM_ACTIVATE is delivered to the window proc because it is
3551 * generated by SetForegroundWindow before the d3d routine
3552 * starts it work. Don't check for it due to focus-follows-mouse
3553 * WMs though. */
3554 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3555 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3556 {0, 0, FALSE, 0},
3558 static const struct message reactivate_messages_filtered[] =
3560 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3561 {0, 0, FALSE, 0},
3563 static const struct message sc_restore_messages[] =
3565 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3566 * processed it. Our wndproc has no way to prevent d3d from
3567 * handling the message. The second DefWindowProc call done by
3568 * our wndproc doesn't do any changes to the window because it
3569 * is already restored due to d3d's handling. */
3570 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3571 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3572 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3573 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3574 {0, 0, FALSE, 0},
3576 static const struct message sc_minimize_messages[] =
3578 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3579 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3580 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3581 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3582 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3583 {0, 0, FALSE, 0},
3585 static const struct message sc_maximize_messages[] =
3587 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3588 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3589 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3590 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3591 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3592 {0, 0, FALSE, 0},
3594 static const struct
3596 DWORD create_flags;
3597 const struct message *focus_loss_messages, *reactivate_messages;
3598 BOOL iconic;
3600 tests[] =
3602 {0, focus_loss_messages, reactivate_messages, TRUE},
3603 {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, reactivate_messages_nowc, FALSE},
3606 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3607 ok(!!d3d9, "Failed to create a D3D object.\n");
3609 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3610 for (i = 0; i < adapter_mode_count; ++i)
3612 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3613 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3615 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3616 continue;
3617 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3618 * refuses to create a device at these sizes. */
3619 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3620 continue;
3622 if (!user32_width)
3624 user32_width = d3ddm.Width;
3625 user32_height = d3ddm.Height;
3626 continue;
3629 /* Make sure the d3d mode is smaller in width or height and at most
3630 * equal in the other dimension than the mode passed to
3631 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3632 * the ChangeDisplaySettings parameters + 12. */
3633 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3634 continue;
3635 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3637 d3d_width = d3ddm.Width;
3638 d3d_height = d3ddm.Height;
3639 break;
3641 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3643 d3d_width = user32_width;
3644 d3d_height = user32_height;
3645 user32_width = d3ddm.Width;
3646 user32_height = d3ddm.Height;
3647 break;
3651 if (!d3d_width)
3653 skip("Could not find adequate modes, skipping mode tests.\n");
3654 IDirect3D9_Release(d3d9);
3655 return;
3658 wc.lpfnWndProc = test_proc;
3659 wc.lpszClassName = "d3d9_test_wndproc_wc";
3660 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3662 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3663 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3664 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3665 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3667 memset(&devmode, 0, sizeof(devmode));
3668 devmode.dmSize = sizeof(devmode);
3669 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
3671 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3672 devmode.dmPelsWidth = user32_width;
3673 devmode.dmPelsHeight = user32_height;
3674 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3675 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3677 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3678 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3679 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3680 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3681 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3682 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3684 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3685 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3687 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3688 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3689 (LONG_PTR)test_proc, proc);
3690 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3691 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3692 (LONG_PTR)test_proc, proc);
3694 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3695 device_window, focus_window, thread_params.dummy_window);
3697 tmp = GetFocus();
3698 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3699 if (thread_params.running_in_foreground)
3701 tmp = GetForegroundWindow();
3702 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3703 thread_params.dummy_window, tmp);
3705 else
3706 skip("Not running in foreground, skip foreground window test\n");
3708 flush_events();
3710 expect_messages = create_messages;
3712 device_desc.device_window = device_window;
3713 device_desc.width = d3d_width;
3714 device_desc.height = d3d_height;
3715 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3716 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3718 skip("Failed to create a D3D device, skipping tests.\n");
3719 goto done;
3722 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3723 expect_messages->message, expect_messages->window, i);
3724 expect_messages = NULL;
3726 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3728 tmp = GetFocus();
3729 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3730 tmp = GetForegroundWindow();
3731 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3733 SetForegroundWindow(focus_window);
3734 flush_events();
3736 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3737 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3738 (LONG_PTR)test_proc, proc, i);
3740 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3741 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3742 (LONG_PTR)test_proc, i);
3744 /* Change the mode while the device is in use and then drop focus. */
3745 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3746 devmode.dmPelsWidth = user32_width;
3747 devmode.dmPelsHeight = user32_height;
3748 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3749 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3751 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3752 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3753 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3754 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3755 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3756 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3758 expect_messages = tests[i].focus_loss_messages;
3759 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3760 * manually changing the focus. It generates the same messages, but the task
3761 * bar still shows the previous foreground window as active, and the window has
3762 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3763 * the device is difficult, see below. */
3764 SetForegroundWindow(GetDesktopWindow());
3765 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3766 expect_messages->message, expect_messages->window, i);
3767 expect_messages = NULL;
3768 tmp = GetFocus();
3769 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3770 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3772 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3773 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3775 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3776 ok(ret, "Failed to get display mode.\n");
3777 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3778 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3779 devmode.dmPelsWidth, devmode.dmPelsHeight);
3781 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3782 * done before the focus window is restored. This makes sense to some extent
3783 * because minimizing the window on focus loss is the application's job if this
3784 * flag is set. */
3785 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3787 ShowWindow(device_window, SW_MINIMIZE);
3788 ShowWindow(device_window, SW_RESTORE);
3790 flush_events();
3792 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3793 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3794 * restore is triggered by the user. */
3795 expect_messages = tests[i].reactivate_messages;
3796 ShowWindow(focus_window, SW_MINIMIZE);
3797 ShowWindow(focus_window, SW_RESTORE);
3798 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3799 SetForegroundWindow(focus_window);
3800 flush_events();
3801 SetForegroundWindow(focus_window);
3802 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3803 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3804 expect_messages->message, expect_messages->window, i);
3805 expect_messages = NULL;
3807 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3808 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3810 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3811 ok(ret, "Failed to get display mode.\n");
3812 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3813 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3814 devmode.dmPelsWidth, devmode.dmPelsHeight);
3816 hr = reset_device(device, &device_desc);
3817 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3819 ShowWindow(device_window, SW_HIDE);
3820 flush_events();
3822 expect_messages = focus_loss_messages_hidden;
3823 windowposchanged_received = 0;
3824 SetForegroundWindow(GetDesktopWindow());
3825 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3826 expect_messages->message, expect_messages->window, i);
3827 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3828 expect_messages = NULL;
3829 flush_events();
3831 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3832 ok(ret, "Failed to get display mode.\n");
3833 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3834 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3836 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3837 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3838 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3839 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3840 flush_events();
3842 syscommand_received = 0;
3843 expect_messages = sc_restore_messages;
3844 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3845 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3846 expect_messages->message, expect_messages->window, i);
3847 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3848 expect_messages = NULL;
3849 flush_events();
3851 expect_messages = sc_minimize_messages;
3852 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
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 flush_events();
3858 expect_messages = sc_maximize_messages;
3859 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3860 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3861 expect_messages->message, expect_messages->window, i);
3862 expect_messages = NULL;
3863 flush_events();
3865 SetForegroundWindow(GetDesktopWindow());
3866 ShowWindow(device_window, SW_MINIMIZE);
3867 ShowWindow(device_window, SW_RESTORE);
3868 ShowWindow(focus_window, SW_MINIMIZE);
3869 ShowWindow(focus_window, SW_RESTORE);
3870 SetForegroundWindow(focus_window);
3871 flush_events();
3873 /* Releasing a device in lost state breaks follow-up tests on native. */
3874 hr = reset_device(device, &device_desc);
3875 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3877 filter_messages = focus_window;
3879 ref = IDirect3DDevice9_Release(device);
3880 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3882 /* Fix up the mode until Wine's device release behavior is fixed. */
3883 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3884 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3886 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3887 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3888 (LONG_PTR)test_proc, proc, i);
3890 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3891 * on native in the test below. It isn't needed anyways. Creating the third
3892 * device will show it again. */
3893 filter_messages = NULL;
3894 ShowWindow(device_window, SW_HIDE);
3895 /* Remove the maximized state from the SYSCOMMAND test while we're not
3896 * interfering with a device. */
3897 ShowWindow(focus_window, SW_SHOWNORMAL);
3898 filter_messages = focus_window;
3900 device_desc.device_window = focus_window;
3901 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3903 skip("Failed to create a D3D device, skipping tests.\n");
3904 goto done;
3906 filter_messages = NULL;
3907 SetForegroundWindow(focus_window); /* For KDE. */
3908 flush_events();
3910 expect_messages = focus_loss_messages_filtered;
3911 windowposchanged_received = 0;
3912 SetForegroundWindow(GetDesktopWindow());
3913 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3914 expect_messages->message, expect_messages->window, i);
3915 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3916 expect_messages = NULL;
3918 /* The window is iconic even though no message was sent. */
3919 ok(!IsIconic(focus_window) == !tests[i].iconic,
3920 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
3922 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3923 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3925 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3926 ShowWindow(focus_window, SW_MINIMIZE);
3928 syscommand_received = 0;
3929 expect_messages = sc_restore_messages;
3930 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3931 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3932 expect_messages->message, expect_messages->window, i);
3933 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3934 expect_messages = NULL;
3935 flush_events();
3937 /* For FVWM. */
3938 ShowWindow(focus_window, SW_RESTORE);
3939 flush_events();
3941 expect_messages = sc_minimize_messages;
3942 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3943 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3944 expect_messages->message, expect_messages->window, i);
3945 expect_messages = NULL;
3946 flush_events();
3948 expect_messages = sc_maximize_messages;
3949 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3950 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3951 expect_messages->message, expect_messages->window, i);
3952 expect_messages = NULL;
3953 flush_events();
3955 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
3956 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
3957 SetForegroundWindow(GetDesktopWindow());
3958 flush_events();
3959 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
3960 flush_events();
3962 expect_messages = reactivate_messages_filtered;
3963 windowposchanged_received = 0;
3964 SetForegroundWindow(focus_window);
3965 flush_events();
3966 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3967 expect_messages->message, expect_messages->window, i);
3968 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
3969 ok(!windowposchanged_received || broken(1),
3970 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3971 expect_messages = NULL;
3973 filter_messages = focus_window;
3974 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3975 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3977 hr = reset_device(device, &device_desc);
3978 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3980 ref = IDirect3DDevice9_Release(device);
3981 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3983 device_desc.device_window = device_window;
3984 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3986 skip("Failed to create a D3D device, skipping tests.\n");
3987 goto done;
3990 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3991 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3992 (LONG_PTR)test_proc, i);
3994 ref = IDirect3DDevice9_Release(device);
3995 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3997 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3998 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3999 (LONG_PTR)DefWindowProcA, proc, i);
4001 done:
4002 filter_messages = NULL;
4003 DestroyWindow(device_window);
4004 DestroyWindow(focus_window);
4005 SetEvent(thread_params.test_finished);
4006 WaitForSingleObject(thread, INFINITE);
4007 CloseHandle(thread);
4010 IDirect3D9_Release(d3d9);
4011 CloseHandle(thread_params.test_finished);
4012 CloseHandle(thread_params.window_created);
4013 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4016 static void test_wndproc_windowed(void)
4018 struct wndproc_thread_param thread_params;
4019 struct device_desc device_desc;
4020 IDirect3DDevice9 *device;
4021 WNDCLASSA wc = {0};
4022 IDirect3D9 *d3d9;
4023 HANDLE thread;
4024 LONG_PTR proc;
4025 HRESULT hr;
4026 ULONG ref;
4027 DWORD res, tid;
4028 HWND tmp;
4030 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4031 ok(!!d3d9, "Failed to create a D3D object.\n");
4033 wc.lpfnWndProc = test_proc;
4034 wc.lpszClassName = "d3d9_test_wndproc_wc";
4035 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4037 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4038 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4039 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4040 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4042 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4043 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4044 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4045 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4046 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4047 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4048 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4049 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4051 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4052 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4054 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4055 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4056 (LONG_PTR)test_proc, proc);
4057 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4058 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4059 (LONG_PTR)test_proc, proc);
4061 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4062 device_window, focus_window, thread_params.dummy_window);
4064 tmp = GetFocus();
4065 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4066 if (thread_params.running_in_foreground)
4068 tmp = GetForegroundWindow();
4069 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4070 thread_params.dummy_window, tmp);
4072 else
4073 skip("Not running in foreground, skip foreground window test\n");
4075 filter_messages = focus_window;
4077 device_desc.device_window = device_window;
4078 device_desc.width = 640;
4079 device_desc.height = 480;
4080 device_desc.flags = 0;
4081 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4083 skip("Failed to create a D3D device, skipping tests.\n");
4084 goto done;
4087 tmp = GetFocus();
4088 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4089 tmp = GetForegroundWindow();
4090 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4091 thread_params.dummy_window, tmp);
4093 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4094 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4095 (LONG_PTR)test_proc, proc);
4097 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4098 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4099 (LONG_PTR)test_proc, proc);
4101 filter_messages = NULL;
4103 device_desc.width = registry_mode.dmPelsWidth;
4104 device_desc.height = registry_mode.dmPelsHeight;
4105 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4106 hr = reset_device(device, &device_desc);
4107 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4109 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4110 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4111 (LONG_PTR)test_proc, proc);
4113 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4114 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4116 device_desc.flags = 0;
4117 hr = reset_device(device, &device_desc);
4118 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4120 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4121 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4122 (LONG_PTR)test_proc, proc);
4124 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4125 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4126 (LONG_PTR)test_proc, proc);
4128 filter_messages = focus_window;
4130 ref = IDirect3DDevice9_Release(device);
4131 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4133 filter_messages = device_window;
4135 device_desc.device_window = focus_window;
4136 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4138 skip("Failed to create a D3D device, skipping tests.\n");
4139 goto done;
4142 filter_messages = NULL;
4144 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4145 hr = reset_device(device, &device_desc);
4146 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4148 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4149 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4150 (LONG_PTR)test_proc, proc);
4152 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4153 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4155 device_desc.flags = 0;
4156 hr = reset_device(device, &device_desc);
4157 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4159 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4160 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4161 (LONG_PTR)test_proc, proc);
4163 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4164 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4165 (LONG_PTR)test_proc, proc);
4167 filter_messages = device_window;
4169 ref = IDirect3DDevice9_Release(device);
4170 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4172 device_desc.device_window = device_window;
4173 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4175 skip("Failed to create a D3D device, skipping tests.\n");
4176 goto done;
4179 filter_messages = NULL;
4181 device_desc.device_window = device_window;
4182 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4183 hr = reset_device(device, &device_desc);
4184 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4186 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4187 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4188 (LONG_PTR)test_proc, proc);
4190 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4191 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4193 device_desc.flags = 0;
4194 hr = reset_device(device, &device_desc);
4195 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4197 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4198 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4199 (LONG_PTR)test_proc, proc);
4201 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4202 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4203 (LONG_PTR)test_proc, proc);
4205 filter_messages = device_window;
4207 ref = IDirect3DDevice9_Release(device);
4208 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4210 done:
4211 filter_messages = NULL;
4212 IDirect3D9_Release(d3d9);
4214 SetEvent(thread_params.test_finished);
4215 WaitForSingleObject(thread, INFINITE);
4216 CloseHandle(thread_params.test_finished);
4217 CloseHandle(thread_params.window_created);
4218 CloseHandle(thread);
4220 DestroyWindow(device_window);
4221 DestroyWindow(focus_window);
4222 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4225 static void test_reset_fullscreen(void)
4227 WNDCLASSEXA wc = {0};
4228 IDirect3DDevice9 *device = NULL;
4229 IDirect3D9 *d3d;
4230 ATOM atom;
4231 struct device_desc device_desc;
4232 static const struct message messages[] =
4234 /* Windows usually sends wparam = TRUE, except on the testbot,
4235 * where it randomly sends FALSE. Ignore it. */
4236 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4237 {0, 0, FALSE, 0},
4240 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4241 ok(!!d3d, "Failed to create a D3D object.\n");
4242 expect_messages = messages;
4244 wc.cbSize = sizeof(wc);
4245 wc.lpfnWndProc = test_proc;
4246 wc.lpszClassName = "test_reset_fullscreen";
4248 atom = RegisterClassExA(&wc);
4249 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4251 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4252 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4253 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4256 * Create a device in windowed mode.
4257 * Since the device is windowed and we haven't called any methods that
4258 * could show the window (such as ShowWindow or SetWindowPos) yet,
4259 * WM_ACTIVATEAPP will not have been sent.
4261 if (!(device = create_device(d3d, device_window, NULL)))
4263 skip("Unable to create device. Skipping test.\n");
4264 goto cleanup;
4268 * Switch to fullscreen mode.
4269 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4270 * message to be sent.
4272 device_desc.width = registry_mode.dmPelsWidth;
4273 device_desc.height = registry_mode.dmPelsHeight;
4274 device_desc.device_window = device_window;
4275 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4276 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4278 flush_events();
4279 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4280 expect_messages = NULL;
4282 cleanup:
4283 if (device) IDirect3DDevice9_Release(device);
4284 IDirect3D9_Release(d3d);
4285 DestroyWindow(device_window);
4286 device_window = focus_window = NULL;
4287 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4291 static inline void set_fpu_cw(WORD cw)
4293 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4294 #define D3D9_TEST_SET_FPU_CW 1
4295 __asm__ volatile ("fnclex");
4296 __asm__ volatile ("fldcw %0" : : "m" (cw));
4297 #elif defined(__i386__) && defined(_MSC_VER)
4298 #define D3D9_TEST_SET_FPU_CW 1
4299 __asm fnclex;
4300 __asm fldcw cw;
4301 #endif
4304 static inline WORD get_fpu_cw(void)
4306 WORD cw = 0;
4307 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4308 #define D3D9_TEST_GET_FPU_CW 1
4309 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4310 #elif defined(__i386__) && defined(_MSC_VER)
4311 #define D3D9_TEST_GET_FPU_CW 1
4312 __asm fnstcw cw;
4313 #endif
4314 return cw;
4317 static WORD callback_cw, callback_set_cw;
4318 static DWORD callback_tid;
4320 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4322 *out = NULL;
4323 return E_NOINTERFACE;
4326 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4328 callback_cw = get_fpu_cw();
4329 set_fpu_cw(callback_set_cw);
4330 callback_tid = GetCurrentThreadId();
4331 return 2;
4334 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4336 callback_cw = get_fpu_cw();
4337 set_fpu_cw(callback_set_cw);
4338 callback_tid = GetCurrentThreadId();
4339 return 1;
4342 static const IUnknownVtbl dummy_object_vtbl =
4344 dummy_object_QueryInterface,
4345 dummy_object_AddRef,
4346 dummy_object_Release,
4349 static const GUID d3d9_private_data_test_guid =
4351 0xfdb37466,
4352 0x428f,
4353 0x4edf,
4354 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4357 static void test_fpu_setup(void)
4359 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4360 struct device_desc device_desc;
4361 IDirect3DDevice9 *device;
4362 HWND window = NULL;
4363 IDirect3D9 *d3d9;
4364 WORD cw;
4365 IDirect3DSurface9 *surface;
4366 HRESULT hr;
4367 IUnknown dummy_object = {&dummy_object_vtbl};
4369 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4370 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4371 ok(!!window, "Failed to create a window.\n");
4372 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4373 ok(!!d3d9, "Failed to create a D3D object.\n");
4375 device_desc.device_window = window;
4376 device_desc.width = 640;
4377 device_desc.height = 480;
4378 device_desc.flags = 0;
4380 set_fpu_cw(0xf60);
4381 cw = get_fpu_cw();
4382 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4384 if (!(device = create_device(d3d9, window, &device_desc)))
4386 skip("Failed to create a 3D device, skipping test.\n");
4387 set_fpu_cw(0x37f);
4388 goto done;
4391 cw = get_fpu_cw();
4392 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4394 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4395 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4397 callback_set_cw = 0xf60;
4398 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4399 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4400 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4401 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4402 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4403 cw = get_fpu_cw();
4404 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4406 callback_cw = 0;
4407 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4408 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4409 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4410 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4411 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4413 callback_set_cw = 0x7f;
4414 set_fpu_cw(0x7f);
4416 IDirect3DSurface9_Release(surface);
4418 callback_cw = 0;
4419 IDirect3DDevice9_Release(device);
4420 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4421 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4423 cw = get_fpu_cw();
4424 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4425 set_fpu_cw(0xf60);
4426 cw = get_fpu_cw();
4427 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4429 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4430 device = create_device(d3d9, window, &device_desc);
4431 ok(device != NULL, "CreateDevice failed.\n");
4433 cw = get_fpu_cw();
4434 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4436 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4437 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4439 callback_cw = 0;
4440 callback_set_cw = 0x37f;
4441 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4442 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4443 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4444 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4445 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4446 cw = get_fpu_cw();
4447 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4449 IDirect3DSurface9_Release(surface);
4451 callback_cw = 0;
4452 IDirect3DDevice9_Release(device);
4453 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4454 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4456 done:
4457 IDirect3D9_Release(d3d9);
4458 DestroyWindow(window);
4459 #endif
4462 static void test_window_style(void)
4464 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4465 LONG device_style, device_exstyle;
4466 LONG focus_style, focus_exstyle;
4467 struct device_desc device_desc;
4468 LONG style, expected_style;
4469 IDirect3DDevice9 *device;
4470 IDirect3D9 *d3d9;
4471 HRESULT hr;
4472 ULONG ref;
4473 BOOL ret;
4474 static const struct
4476 DWORD device_flags;
4477 LONG style, focus_loss_style, exstyle;
4479 tests[] =
4481 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4482 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4484 unsigned int i;
4486 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4487 ok(!!d3d9, "Failed to create a D3D object.\n");
4488 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4490 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
4492 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4493 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4494 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4495 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4497 device_style = GetWindowLongA(device_window, GWL_STYLE);
4498 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4499 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4500 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4502 GetWindowRect(focus_window, &focus_rect);
4503 GetWindowRect(device_window, &device_rect);
4505 device_desc.device_window = device_window;
4506 device_desc.width = registry_mode.dmPelsWidth;
4507 device_desc.height = registry_mode.dmPelsHeight;
4508 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4509 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4511 skip("Failed to create a D3D device, skipping tests.\n");
4512 DestroyWindow(device_window);
4513 DestroyWindow(focus_window);
4514 break;
4517 style = GetWindowLongA(device_window, GWL_STYLE);
4518 expected_style = device_style | tests[i].style;
4519 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4520 expected_style, style, i);
4521 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4522 expected_style = device_exstyle | tests[i].exstyle;
4523 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4524 expected_style, style, i);
4526 style = GetWindowLongA(focus_window, GWL_STYLE);
4527 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4528 focus_style, style, i);
4529 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4530 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4531 focus_exstyle, style, i);
4533 GetWindowRect(device_window, &r);
4534 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4535 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4536 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4537 else
4538 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4539 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4540 GetClientRect(device_window, &r2);
4541 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4542 GetWindowRect(focus_window, &r);
4543 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4544 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4546 device_desc.flags = 0;
4547 hr = reset_device(device, &device_desc);
4548 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4550 style = GetWindowLongA(device_window, GWL_STYLE);
4551 expected_style = device_style | tests[i].style;
4552 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4553 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4554 expected_style, style, i);
4555 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4556 expected_style = device_exstyle | tests[i].exstyle;
4557 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4558 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4559 expected_style, style, i);
4561 style = GetWindowLongA(focus_window, GWL_STYLE);
4562 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4563 focus_style, style, i);
4564 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4565 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4566 focus_exstyle, style, i);
4568 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4569 hr = reset_device(device, &device_desc);
4570 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4571 ret = SetForegroundWindow(GetDesktopWindow());
4572 ok(ret, "Failed to set foreground window.\n");
4574 style = GetWindowLongA(device_window, GWL_STYLE);
4575 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4576 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4577 expected_style, style);
4578 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4579 expected_style = device_exstyle | tests[i].exstyle;
4580 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4581 expected_style, style);
4583 style = GetWindowLongA(focus_window, GWL_STYLE);
4584 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4585 focus_style, style);
4586 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4587 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4588 focus_exstyle, style);
4590 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4591 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4592 * like a good idea to reset it first. */
4593 ShowWindow(focus_window, SW_MINIMIZE);
4594 ShowWindow(focus_window, SW_RESTORE);
4595 ret = SetForegroundWindow(focus_window);
4596 ok(ret, "Failed to set foreground window.\n");
4597 flush_events();
4598 hr = reset_device(device, &device_desc);
4599 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4601 ref = IDirect3DDevice9_Release(device);
4602 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4604 DestroyWindow(device_window);
4605 DestroyWindow(focus_window);
4607 IDirect3D9_Release(d3d9);
4610 static const POINT *expect_pos;
4612 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4614 if (message == WM_MOUSEMOVE)
4616 if (expect_pos && expect_pos->x && expect_pos->y)
4618 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4620 ClientToScreen(window, &p);
4621 if (expect_pos->x == p.x && expect_pos->y == p.y)
4622 ++expect_pos;
4626 return DefWindowProcA(window, message, wparam, lparam);
4629 static void test_cursor_pos(void)
4631 IDirect3DSurface9 *cursor;
4632 IDirect3DDevice9 *device;
4633 WNDCLASSA wc = {0};
4634 IDirect3D9 *d3d9;
4635 UINT refcount;
4636 HWND window;
4637 HRESULT hr;
4638 BOOL ret;
4640 /* Note that we don't check for movement we're not supposed to receive.
4641 * That's because it's hard to distinguish from the user accidentally
4642 * moving the mouse. */
4643 static const POINT points[] =
4645 {50, 50},
4646 {75, 75},
4647 {100, 100},
4648 {125, 125},
4649 {150, 150},
4650 {125, 125},
4651 {150, 150},
4652 {150, 150},
4653 {0, 0},
4656 wc.lpfnWndProc = test_cursor_proc;
4657 wc.lpszClassName = "d3d9_test_cursor_wc";
4658 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4659 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4660 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4661 ShowWindow(window, SW_SHOW);
4662 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4663 ok(!!d3d9, "Failed to create a D3D object.\n");
4665 device = create_device(d3d9, window, NULL);
4666 if (!device)
4668 skip("Failed to create a D3D device, skipping tests.\n");
4669 goto done;
4672 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4673 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4674 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4675 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4676 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4677 IDirect3DSurface9_Release(cursor);
4678 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4679 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4681 flush_events();
4682 expect_pos = points;
4684 ret = SetCursorPos(50, 50);
4685 ok(ret, "Failed to set cursor position.\n");
4686 flush_events();
4688 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4689 flush_events();
4690 /* SetCursorPosition() eats duplicates. */
4691 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4692 flush_events();
4694 ret = SetCursorPos(100, 100);
4695 ok(ret, "Failed to set cursor position.\n");
4696 flush_events();
4697 /* Even if the position was set with SetCursorPos(). */
4698 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4699 flush_events();
4701 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4702 flush_events();
4703 ret = SetCursorPos(150, 150);
4704 ok(ret, "Failed to set cursor position.\n");
4705 flush_events();
4706 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4707 flush_events();
4709 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4710 flush_events();
4711 /* SetCursorPos() doesn't. */
4712 ret = SetCursorPos(150, 150);
4713 ok(ret, "Failed to set cursor position.\n");
4714 flush_events();
4716 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4717 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4719 refcount = IDirect3DDevice9_Release(device);
4720 ok(!refcount, "Device has %u references left.\n", refcount);
4721 done:
4722 DestroyWindow(window);
4723 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4724 IDirect3D9_Release(d3d9);
4727 static void test_mode_change(void)
4729 RECT d3d_rect, focus_rect, r;
4730 struct device_desc device_desc;
4731 IDirect3DSurface9 *backbuffer;
4732 IDirect3DDevice9 *device;
4733 D3DSURFACE_DESC desc;
4734 IDirect3D9 *d3d9;
4735 DEVMODEW devmode;
4736 ULONG refcount;
4737 UINT adapter_mode_count, i;
4738 HRESULT hr;
4739 DWORD ret;
4740 LONG change_ret;
4741 D3DDISPLAYMODE d3ddm;
4742 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4744 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4745 ok(!!d3d9, "Failed to create a D3D object.\n");
4747 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4748 for (i = 0; i < adapter_mode_count; ++i)
4750 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4751 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4753 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4754 continue;
4755 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4756 * refuses to create a device at these sizes. */
4757 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4758 continue;
4760 if (!user32_width)
4762 user32_width = d3ddm.Width;
4763 user32_height = d3ddm.Height;
4764 continue;
4767 /* Make sure the d3d mode is smaller in width or height and at most
4768 * equal in the other dimension than the mode passed to
4769 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4770 * the ChangeDisplaySettings parameters + 12. */
4771 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4772 continue;
4773 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4775 d3d_width = d3ddm.Width;
4776 d3d_height = d3ddm.Height;
4777 break;
4779 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4781 d3d_width = user32_width;
4782 d3d_height = user32_height;
4783 user32_width = d3ddm.Width;
4784 user32_height = d3ddm.Height;
4785 break;
4789 if (!d3d_width)
4791 skip("Could not find adequate modes, skipping mode tests.\n");
4792 IDirect3D9_Release(d3d9);
4793 return;
4796 memset(&devmode, 0, sizeof(devmode));
4797 devmode.dmSize = sizeof(devmode);
4798 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4799 devmode.dmPelsWidth = user32_width;
4800 devmode.dmPelsHeight = user32_height;
4801 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4802 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4804 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4805 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4806 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4807 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4809 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4810 GetWindowRect(focus_window, &focus_rect);
4812 device_desc.device_window = device_window;
4813 device_desc.width = d3d_width;
4814 device_desc.height = d3d_height;
4815 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4816 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4818 skip("Failed to create a D3D device, skipping tests.\n");
4819 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4820 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4821 goto done;
4824 devmode.dmPelsWidth = user32_width;
4825 devmode.dmPelsHeight = user32_height;
4826 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4827 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4829 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4830 ok(ret, "Failed to get display mode.\n");
4831 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4832 "Expected resolution %ux%u, got %ux%u.\n",
4833 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4835 GetWindowRect(device_window, &r);
4836 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
4837 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
4838 GetWindowRect(focus_window, &r);
4839 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
4840 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
4842 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4843 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
4844 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
4845 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
4846 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4847 desc.Width, d3d_width);
4848 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4849 desc.Height, d3d_height);
4850 IDirect3DSurface9_Release(backbuffer);
4852 refcount = IDirect3DDevice9_Release(device);
4853 ok(!refcount, "Device has %u references left.\n", refcount);
4855 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4856 ok(ret, "Failed to get display mode.\n");
4857 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4858 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4859 "Expected resolution %ux%u, got %ux%u.\n",
4860 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4862 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4863 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4865 /* The mode restore also happens when the device was created at the original screen size. */
4867 device_desc.device_window = device_window;
4868 device_desc.width = registry_mode.dmPelsWidth;
4869 device_desc.height = registry_mode.dmPelsHeight;
4870 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4871 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4873 devmode.dmPelsWidth = user32_width;
4874 devmode.dmPelsHeight = user32_height;
4875 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4876 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4878 refcount = IDirect3DDevice9_Release(device);
4879 ok(!refcount, "Device has %u references left.\n", refcount);
4881 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4882 ok(ret, "Failed to get display mode.\n");
4883 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4884 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4885 "Expected resolution %ux%u, got %ux%u.\n",
4886 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4888 done:
4889 DestroyWindow(device_window);
4890 DestroyWindow(focus_window);
4891 IDirect3D9_Release(d3d9);
4894 static void test_device_window_reset(void)
4896 RECT fullscreen_rect, device_rect, r;
4897 struct device_desc device_desc;
4898 IDirect3DDevice9 *device;
4899 WNDCLASSA wc = {0};
4900 IDirect3D9 *d3d9;
4901 LONG_PTR proc;
4902 HRESULT hr;
4903 ULONG ref;
4905 wc.lpfnWndProc = test_proc;
4906 wc.lpszClassName = "d3d9_test_wndproc_wc";
4907 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4909 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4910 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4911 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4912 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4913 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4914 ok(!!d3d9, "Failed to create a D3D object.\n");
4916 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4917 GetWindowRect(device_window, &device_rect);
4919 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4920 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4921 (LONG_PTR)test_proc, proc);
4922 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4923 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4924 (LONG_PTR)test_proc, proc);
4926 device_desc.device_window = NULL;
4927 device_desc.width = registry_mode.dmPelsWidth;
4928 device_desc.height = registry_mode.dmPelsHeight;
4929 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4930 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4932 skip("Failed to create a D3D device, skipping tests.\n");
4933 goto done;
4936 GetWindowRect(focus_window, &r);
4937 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4938 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4939 GetWindowRect(device_window, &r);
4940 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
4941 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
4943 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4944 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4945 (LONG_PTR)test_proc, proc);
4946 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4947 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4949 device_desc.device_window = device_window;
4950 hr = reset_device(device, &device_desc);
4951 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4953 GetWindowRect(focus_window, &r);
4954 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4955 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4956 GetWindowRect(device_window, &r);
4957 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4958 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4960 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4961 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4962 (LONG_PTR)test_proc, proc);
4963 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4964 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4966 ref = IDirect3DDevice9_Release(device);
4967 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4969 done:
4970 IDirect3D9_Release(d3d9);
4971 DestroyWindow(device_window);
4972 DestroyWindow(focus_window);
4973 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4976 static void test_reset_resources(void)
4978 IDirect3DSurface9 *surface, *rt;
4979 IDirect3DTexture9 *texture;
4980 IDirect3DDevice9 *device;
4981 IDirect3D9 *d3d9;
4982 unsigned int i;
4983 D3DCAPS9 caps;
4984 HWND window;
4985 HRESULT hr;
4986 ULONG ref;
4988 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
4989 0, 0, 640, 480, 0, 0, 0, 0);
4990 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4991 ok(!!d3d9, "Failed to create a D3D object.\n");
4993 if (!(device = create_device(d3d9, window, NULL)))
4995 skip("Failed to create a D3D device, skipping tests.\n");
4996 goto done;
4999 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5000 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5002 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5003 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5004 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5005 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5006 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5007 IDirect3DSurface9_Release(surface);
5009 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5011 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5012 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5013 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5014 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5015 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5016 IDirect3DTexture9_Release(texture);
5017 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5018 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5019 IDirect3DSurface9_Release(surface);
5022 hr = reset_device(device, NULL);
5023 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5025 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5026 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5027 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5028 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5029 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5030 IDirect3DSurface9_Release(surface);
5031 IDirect3DSurface9_Release(rt);
5033 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5035 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5036 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5039 ref = IDirect3DDevice9_Release(device);
5040 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5042 done:
5043 IDirect3D9_Release(d3d9);
5044 DestroyWindow(window);
5047 static void test_set_rt_vp_scissor(void)
5049 IDirect3DStateBlock9 *stateblock;
5050 IDirect3DDevice9 *device;
5051 IDirect3DSurface9 *rt;
5052 IDirect3D9 *d3d9;
5053 D3DVIEWPORT9 vp;
5054 UINT refcount;
5055 HWND window;
5056 HRESULT hr;
5057 RECT rect;
5059 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5060 0, 0, 640, 480, 0, 0, 0, 0);
5061 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5062 ok(!!d3d9, "Failed to create a D3D object.\n");
5063 if (!(device = create_device(d3d9, window, NULL)))
5065 skip("Failed to create a D3D device, skipping tests.\n");
5066 DestroyWindow(window);
5067 return;
5070 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5071 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5072 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5074 hr = IDirect3DDevice9_GetViewport(device, &vp);
5075 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5076 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5077 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5078 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5079 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5080 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5081 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5083 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5084 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5085 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5086 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5088 hr = IDirect3DDevice9_BeginStateBlock(device);
5089 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5091 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5092 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5094 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5095 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5096 IDirect3DStateBlock9_Release(stateblock);
5098 hr = IDirect3DDevice9_GetViewport(device, &vp);
5099 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5100 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5101 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5102 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5103 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5104 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5105 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5107 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5108 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5109 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5110 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5112 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5113 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5115 vp.X = 10;
5116 vp.Y = 20;
5117 vp.Width = 30;
5118 vp.Height = 40;
5119 vp.MinZ = 0.25f;
5120 vp.MaxZ = 0.75f;
5121 hr = IDirect3DDevice9_SetViewport(device, &vp);
5122 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5124 SetRect(&rect, 50, 60, 70, 80);
5125 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5126 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5128 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5129 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5131 hr = IDirect3DDevice9_GetViewport(device, &vp);
5132 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5133 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5134 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5135 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5136 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5137 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5138 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5140 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5141 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5142 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5143 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5145 IDirect3DSurface9_Release(rt);
5146 refcount = IDirect3DDevice9_Release(device);
5147 ok(!refcount, "Device has %u references left.\n", refcount);
5148 IDirect3D9_Release(d3d9);
5149 DestroyWindow(window);
5152 static void test_volume_get_container(void)
5154 IDirect3DVolumeTexture9 *texture = NULL;
5155 IDirect3DVolume9 *volume = NULL;
5156 IDirect3DDevice9 *device;
5157 IUnknown *container;
5158 IDirect3D9 *d3d9;
5159 ULONG refcount;
5160 D3DCAPS9 caps;
5161 HWND window;
5162 HRESULT hr;
5164 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5165 0, 0, 640, 480, 0, 0, 0, 0);
5166 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5167 ok(!!d3d9, "Failed to create a D3D object.\n");
5168 if (!(device = create_device(d3d9, window, NULL)))
5170 skip("Failed to create a D3D device, skipping tests.\n");
5171 IDirect3D9_Release(d3d9);
5172 DestroyWindow(window);
5173 return;
5176 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5177 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5178 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5180 skip("No volume texture support, skipping tests.\n");
5181 IDirect3DDevice9_Release(device);
5182 IDirect3D9_Release(d3d9);
5183 DestroyWindow(window);
5184 return;
5187 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5188 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5189 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5190 ok(!!texture, "Got unexpected texture %p.\n", texture);
5192 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5193 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5194 ok(!!volume, "Got unexpected volume %p.\n", volume);
5196 /* These should work... */
5197 container = NULL;
5198 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5199 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5200 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5201 IUnknown_Release(container);
5203 container = NULL;
5204 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5205 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5206 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5207 IUnknown_Release(container);
5209 container = NULL;
5210 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5211 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5212 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5213 IUnknown_Release(container);
5215 container = NULL;
5216 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5217 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5218 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5219 IUnknown_Release(container);
5221 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5222 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5223 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5224 ok(!container, "Got unexpected container %p.\n", container);
5226 IDirect3DVolume9_Release(volume);
5227 IDirect3DVolumeTexture9_Release(texture);
5228 refcount = IDirect3DDevice9_Release(device);
5229 ok(!refcount, "Device has %u references left.\n", refcount);
5230 IDirect3D9_Release(d3d9);
5231 DestroyWindow(window);
5234 static void test_volume_resource(void)
5236 IDirect3DVolumeTexture9 *texture;
5237 IDirect3DResource9 *resource;
5238 IDirect3DVolume9 *volume;
5239 IDirect3DDevice9 *device;
5240 IDirect3D9 *d3d9;
5241 ULONG refcount;
5242 D3DCAPS9 caps;
5243 HWND window;
5244 HRESULT hr;
5246 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5247 0, 0, 640, 480, 0, 0, 0, 0);
5248 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5249 ok(!!d3d9, "Failed to create a D3D object.\n");
5250 if (!(device = create_device(d3d9, window, NULL)))
5252 skip("Failed to create a D3D device, skipping tests.\n");
5253 IDirect3D9_Release(d3d9);
5254 DestroyWindow(window);
5255 return;
5258 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5259 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5260 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5262 skip("No volume texture support, skipping tests.\n");
5263 IDirect3DDevice9_Release(device);
5264 IDirect3D9_Release(d3d9);
5265 DestroyWindow(window);
5266 return;
5269 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5270 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5271 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5272 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5273 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5274 IDirect3DVolumeTexture9_Release(texture);
5276 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5277 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5279 IDirect3DVolume9_Release(volume);
5280 refcount = IDirect3DDevice9_Release(device);
5281 ok(!refcount, "Device has %u references left.\n", refcount);
5282 IDirect3D9_Release(d3d9);
5283 DestroyWindow(window);
5286 static void test_vb_lock_flags(void)
5288 static const struct
5290 DWORD flags;
5291 const char *debug_string;
5292 HRESULT win7_result;
5294 test_data[] =
5296 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5297 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5298 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5299 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5300 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5301 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5302 /* Completely bogus flags aren't an error. */
5303 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5305 IDirect3DVertexBuffer9 *buffer;
5306 IDirect3DDevice9 *device;
5307 IDirect3D9 *d3d9;
5308 unsigned int i;
5309 ULONG refcount;
5310 HWND window;
5311 HRESULT hr;
5312 void *data;
5314 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5315 0, 0, 640, 480, 0, 0, 0, 0);
5316 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5317 ok(!!d3d9, "Failed to create a D3D object.\n");
5318 if (!(device = create_device(d3d9, window, NULL)))
5320 skip("Failed to create a D3D device, skipping tests.\n");
5321 IDirect3D9_Release(d3d9);
5322 DestroyWindow(window);
5323 return;
5326 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5327 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5329 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5331 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5332 /* Windows XP always returns D3D_OK even with flags that don't make
5333 * sense. Windows 7 returns an error. At least one game (Shaiya)
5334 * depends on the Windows XP result, so mark the Windows 7 behavior as
5335 * broken. */
5336 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5337 hr, test_data[i].debug_string);
5338 if (SUCCEEDED(hr))
5340 ok(!!data, "Got unexpected data %p.\n", data);
5341 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5342 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5346 IDirect3DVertexBuffer9_Release(buffer);
5347 refcount = IDirect3DDevice9_Release(device);
5348 ok(!refcount, "Device has %u references left.\n", refcount);
5349 IDirect3D9_Release(d3d9);
5350 DestroyWindow(window);
5353 static const char *debug_d3dpool(D3DPOOL pool)
5355 switch (pool)
5357 case D3DPOOL_DEFAULT:
5358 return "D3DPOOL_DEFAULT";
5359 case D3DPOOL_SYSTEMMEM:
5360 return "D3DPOOL_SYSTEMMEM";
5361 case D3DPOOL_SCRATCH:
5362 return "D3DPOOL_SCRATCH";
5363 case D3DPOOL_MANAGED:
5364 return "D3DPOOL_MANAGED";
5365 default:
5366 return "unknown pool";
5370 static void test_vertex_buffer_alignment(void)
5372 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5373 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5374 IDirect3DVertexBuffer9 *buffer = NULL;
5375 const unsigned int align = 16;
5376 IDirect3DDevice9 *device;
5377 unsigned int i, j;
5378 IDirect3D9 *d3d9;
5379 ULONG refcount;
5380 HWND window;
5381 HRESULT hr;
5382 void *data;
5384 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5385 0, 0, 640, 480, 0, 0, 0, 0);
5386 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5387 ok(!!d3d9, "Failed to create a D3D object.\n");
5388 if (!(device = create_device(d3d9, window, NULL)))
5390 skip("Failed to create a D3D device, skipping tests.\n");
5391 IDirect3D9_Release(d3d9);
5392 DestroyWindow(window);
5393 return;
5396 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
5398 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5400 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5401 if (pools[j] == D3DPOOL_SCRATCH)
5402 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5403 else
5404 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5405 debug_d3dpool(pools[j]), sizes[i], hr);
5406 if (FAILED(hr))
5407 continue;
5409 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5410 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5411 ok(!((DWORD_PTR)data & (align - 1)),
5412 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5413 data, align, sizes[i], debug_d3dpool(pools[j]));
5414 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5415 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5416 IDirect3DVertexBuffer9_Release(buffer);
5420 refcount = IDirect3DDevice9_Release(device);
5421 ok(!refcount, "Device has %u references left.\n", refcount);
5422 IDirect3D9_Release(d3d9);
5423 DestroyWindow(window);
5426 static void test_query_support(void)
5428 static const D3DQUERYTYPE queries[] =
5430 D3DQUERYTYPE_VCACHE,
5431 D3DQUERYTYPE_RESOURCEMANAGER,
5432 D3DQUERYTYPE_VERTEXSTATS,
5433 D3DQUERYTYPE_EVENT,
5434 D3DQUERYTYPE_OCCLUSION,
5435 D3DQUERYTYPE_TIMESTAMP,
5436 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5437 D3DQUERYTYPE_TIMESTAMPFREQ,
5438 D3DQUERYTYPE_PIPELINETIMINGS,
5439 D3DQUERYTYPE_INTERFACETIMINGS,
5440 D3DQUERYTYPE_VERTEXTIMINGS,
5441 D3DQUERYTYPE_PIXELTIMINGS,
5442 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5443 D3DQUERYTYPE_CACHEUTILIZATION,
5445 IDirect3DQuery9 *query = NULL;
5446 IDirect3DDevice9 *device;
5447 IDirect3D9 *d3d9;
5448 unsigned int i;
5449 ULONG refcount;
5450 BOOL supported;
5451 HWND window;
5452 HRESULT hr;
5454 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5455 0, 0, 640, 480, 0, 0, 0, 0);
5456 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5457 ok(!!d3d9, "Failed to create a D3D object.\n");
5458 if (!(device = create_device(d3d9, window, NULL)))
5460 skip("Failed to create a D3D device, skipping tests.\n");
5461 IDirect3D9_Release(d3d9);
5462 DestroyWindow(window);
5463 return;
5466 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
5468 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5469 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5471 supported = hr == D3D_OK;
5473 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5474 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5476 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5477 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5479 if (query)
5481 IDirect3DQuery9_Release(query);
5482 query = NULL;
5486 refcount = IDirect3DDevice9_Release(device);
5487 ok(!refcount, "Device has %u references left.\n", refcount);
5488 IDirect3D9_Release(d3d9);
5489 DestroyWindow(window);
5492 static void test_occlusion_query_states(void)
5494 static const float quad[] =
5496 -1.0f, -1.0f, 0.0f,
5497 -1.0f, 1.0f, 0.0f,
5498 1.0f, 1.0f, 0.0f,
5499 1.0f, -1.0f, 0.0f,
5501 struct device_desc device_desc;
5502 IDirect3DQuery9 *query = NULL;
5503 unsigned int data_size, i;
5504 IDirect3DDevice9 *device;
5505 IDirect3D9 *d3d9;
5506 ULONG refcount;
5507 HWND window;
5508 HRESULT hr;
5509 union
5511 WORD word[4];
5512 DWORD dword[2];
5513 } data;
5514 BOOL broken_occlusion = FALSE;
5515 DWORD expected = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5517 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5518 0, 0, 640, 480, 0, 0, 0, 0);
5519 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5520 ok(!!d3d9, "Failed to create a D3D object.\n");
5521 device_desc.device_window = window;
5522 device_desc.width = registry_mode.dmPelsWidth;
5523 device_desc.height = registry_mode.dmPelsHeight;
5524 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5525 if (!(device = create_device(d3d9, window, &device_desc)))
5527 skip("Failed to create a D3D device, skipping tests.\n");
5528 IDirect3D9_Release(d3d9);
5529 DestroyWindow(window);
5530 return;
5533 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5534 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5535 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5536 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5537 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5538 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5540 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5541 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5542 if (!query)
5544 skip("Occlusion queries are not supported, skipping tests.\n");
5545 IDirect3DDevice9_Release(device);
5546 IDirect3D9_Release(d3d9);
5547 DestroyWindow(window);
5548 return;
5551 data_size = IDirect3DQuery9_GetDataSize(query);
5552 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5554 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5555 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5556 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5557 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5559 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5560 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5561 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5562 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5563 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5564 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5566 data.dword[0] = 0x12345678;
5567 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5568 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5569 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5570 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5571 if (hr == D3D_OK)
5572 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5574 hr = IDirect3DDevice9_BeginScene(device);
5575 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5576 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5577 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5578 hr = IDirect3DDevice9_EndScene(device);
5579 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5581 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5582 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5583 for (i = 0; i < 500; ++i)
5585 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5586 break;
5587 Sleep(10);
5589 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5591 memset(&data, 0xff, sizeof(data));
5592 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5593 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5594 ok(data.dword[0] == expected || broken(!data.dword[0]),
5595 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5596 if (!data.dword[0])
5598 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5599 broken_occlusion = TRUE;
5602 memset(&data, 0xff, sizeof(data));
5603 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5604 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5605 if (!broken_occlusion)
5606 ok(data.word[0] == (WORD)expected,
5607 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5608 ok(data.word[1] == 0xffff,
5609 "data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5611 memset(&data, 0xf0, sizeof(data));
5612 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5613 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5614 if (!broken_occlusion)
5615 ok(data.dword[0] == expected,
5616 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5617 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5618 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5619 on AMD and Nvidia respectively). */
5620 if (0)
5622 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5623 data.dword[1]);
5626 memset(&data, 0xff, sizeof(data));
5627 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5628 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5629 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5631 /* This crashes on Windows. */
5632 if (0)
5634 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5635 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5638 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5639 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5640 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5642 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5643 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5645 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5647 IDirect3DQuery9_Release(query);
5648 refcount = IDirect3DDevice9_Release(device);
5649 ok(!refcount, "Device has %u references left.\n", refcount);
5650 IDirect3D9_Release(d3d9);
5651 DestroyWindow(window);
5654 static void test_timestamp_query(void)
5656 static const float quad[] =
5658 -1.0f, -1.0f, 0.0f,
5659 -1.0f, 1.0f, 0.0f,
5660 1.0f, 1.0f, 0.0f,
5661 1.0f, -1.0f, 0.0f,
5663 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5664 unsigned int data_size, i;
5665 IDirect3DDevice9 *device;
5666 IDirect3D9 *d3d9;
5667 ULONG refcount;
5668 HWND window;
5669 HRESULT hr;
5670 DWORD timestamp[2], freq[2];
5671 WORD disjoint[2];
5673 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5674 0, 0, 640, 480, 0, 0, 0, 0);
5675 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5676 ok(!!d3d9, "Failed to create a D3D object.\n");
5677 if (!(device = create_device(d3d9, window, NULL)))
5679 skip("Failed to create a D3D device, skipping tests.\n");
5680 IDirect3D9_Release(d3d9);
5681 DestroyWindow(window);
5682 return;
5685 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5686 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5687 if (FAILED(hr))
5689 skip("Timestamp queries are not supported, skipping tests.\n");
5690 IDirect3DDevice9_Release(device);
5691 IDirect3D9_Release(d3d9);
5692 DestroyWindow(window);
5693 return;
5695 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5696 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5698 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5699 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5700 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5701 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5703 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
5704 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5705 data_size = IDirect3DQuery9_GetDataSize(query);
5706 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5708 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
5709 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5710 for (i = 0; i < 500; ++i)
5712 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5713 break;
5714 Sleep(10);
5716 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5718 memset(freq, 0xff, sizeof(freq));
5719 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5720 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5721 ok(freq[1] == 0xffffffff,
5722 "freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
5723 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
5724 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5725 ok(freq[1] != 0xffffffff, "high bytes of freq were not modified (0x%.8x).\n",
5726 freq[1]);
5728 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5729 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5730 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5731 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5733 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5734 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5735 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5736 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5737 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5738 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5740 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5741 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5743 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5744 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5745 hr = IDirect3DDevice9_BeginScene(device);
5746 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5747 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5748 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5749 hr = IDirect3DDevice9_EndScene(device);
5750 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5752 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5753 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5754 for (i = 0; i < 500; ++i)
5756 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5757 break;
5758 Sleep(10);
5760 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5762 memset(timestamp, 0xff, sizeof(timestamp));
5763 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5764 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5765 ok(timestamp[1] == 0xffffffff,
5766 "timestamp was modified outside of the expected size (0x%.8x).\n",
5767 timestamp[1]);
5769 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5770 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5771 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5772 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5773 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5774 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5776 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5777 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5778 for (i = 0; i < 500; ++i)
5780 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5781 break;
5782 Sleep(10);
5784 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5786 memset(disjoint, 0xff, sizeof(disjoint));
5787 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5788 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5789 ok(disjoint[1] == 0xffff,
5790 "disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
5791 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
5792 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5793 ok(disjoint[1] != 0xffff, "high bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
5795 /* It's not strictly necessary for the TIMESTAMP query to be inside
5796 * a TIMESTAMP_DISJOINT query. */
5797 hr = IDirect3DDevice9_BeginScene(device);
5798 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5799 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5800 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5801 hr = IDirect3DDevice9_EndScene(device);
5802 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5804 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5805 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5806 for (i = 0; i < 500; ++i)
5808 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5809 break;
5810 Sleep(10);
5812 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5813 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5814 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5816 IDirect3DQuery9_Release(query);
5817 IDirect3DQuery9_Release(disjoint_query);
5818 IDirect3DQuery9_Release(freq_query);
5819 refcount = IDirect3DDevice9_Release(device);
5820 ok(!refcount, "Device has %u references left.\n", refcount);
5821 IDirect3D9_Release(d3d9);
5822 DestroyWindow(window);
5825 static void test_get_set_vertex_shader(void)
5827 IDirect3DVertexShader9 *current_shader = NULL;
5828 IDirect3DVertexShader9 *shader = NULL;
5829 const IDirect3DVertexShader9Vtbl *shader_vtbl;
5830 IDirect3DDevice9 *device;
5831 ULONG refcount, i;
5832 IDirect3D9 *d3d;
5833 D3DCAPS9 caps;
5834 HWND window;
5835 HRESULT hr;
5837 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5838 0, 0, 640, 480, 0, 0, 0, 0);
5839 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5840 ok(!!d3d, "Failed to create a D3D object.\n");
5841 if (!(device = create_device(d3d, window, NULL)))
5843 skip("Failed to create a D3D device, skipping tests.\n");
5844 IDirect3D9_Release(d3d);
5845 DestroyWindow(window);
5846 return;
5849 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5850 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5851 if (!(caps.VertexShaderVersion & 0xffff))
5853 skip("No vertex shader support, skipping tests.\n");
5854 IDirect3DDevice9_Release(device);
5855 IDirect3D9_Release(d3d);
5856 DestroyWindow(window);
5857 return;
5860 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
5861 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5862 ok(!!shader, "Got unexpected shader %p.\n", shader);
5864 /* SetVertexShader() should not touch the shader's refcount. */
5865 i = get_refcount((IUnknown *)shader);
5866 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5867 refcount = get_refcount((IUnknown *)shader);
5868 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5869 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5871 /* GetVertexShader() should increase the shader's refcount by one. */
5872 i = refcount + 1;
5873 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
5874 refcount = get_refcount((IUnknown *)shader);
5875 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
5876 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5877 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
5878 IDirect3DVertexShader9_Release(current_shader);
5880 /* SetVertexShader() with a bogus shader vtbl */
5881 shader_vtbl = shader->lpVtbl;
5882 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
5883 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5884 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5885 shader->lpVtbl = NULL;
5886 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5887 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5888 shader->lpVtbl = shader_vtbl;
5890 IDirect3DVertexShader9_Release(shader);
5891 refcount = IDirect3DDevice9_Release(device);
5892 ok(!refcount, "Device has %u references left.\n", refcount);
5893 IDirect3D9_Release(d3d);
5894 DestroyWindow(window);
5897 static void test_vertex_shader_constant(void)
5899 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};
5900 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
5901 IDirect3DDevice9 *device;
5902 IDirect3D9 *d3d;
5903 ULONG refcount;
5904 D3DCAPS9 caps;
5905 DWORD consts;
5906 HWND window;
5907 HRESULT hr;
5909 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5910 0, 0, 640, 480, 0, 0, 0, 0);
5911 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5912 ok(!!d3d, "Failed to create a D3D object.\n");
5913 if (!(device = create_device(d3d, window, NULL)))
5915 skip("Failed to create a D3D device, skipping tests.\n");
5916 IDirect3D9_Release(d3d);
5917 DestroyWindow(window);
5918 return;
5921 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5922 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5923 if (!(caps.VertexShaderVersion & 0xffff))
5925 skip("No vertex shader support, skipping tests.\n");
5926 IDirect3DDevice9_Release(device);
5927 IDirect3D9_Release(d3d);
5928 DestroyWindow(window);
5929 return;
5931 consts = caps.MaxVertexShaderConst;
5933 /* A simple check that the stuff works at all. */
5934 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
5935 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5937 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
5938 * consts from MAX - 1. */
5939 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
5940 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5941 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
5942 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5943 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
5944 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5945 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
5946 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5948 /* Constant -1. */
5949 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
5950 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5952 refcount = IDirect3DDevice9_Release(device);
5953 ok(!refcount, "Device has %u references left.\n", refcount);
5954 IDirect3D9_Release(d3d);
5955 DestroyWindow(window);
5958 static void test_get_set_pixel_shader(void)
5960 IDirect3DPixelShader9 *current_shader = NULL;
5961 IDirect3DPixelShader9 *shader = NULL;
5962 const IDirect3DPixelShader9Vtbl *shader_vtbl;
5963 IDirect3DDevice9 *device;
5964 ULONG refcount, i;
5965 IDirect3D9 *d3d;
5966 D3DCAPS9 caps;
5967 HWND window;
5968 HRESULT hr;
5970 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5971 0, 0, 640, 480, 0, 0, 0, 0);
5972 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5973 ok(!!d3d, "Failed to create a D3D object.\n");
5974 if (!(device = create_device(d3d, window, NULL)))
5976 skip("Failed to create a D3D device, skipping tests.\n");
5977 IDirect3D9_Release(d3d);
5978 DestroyWindow(window);
5979 return;
5982 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5983 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5984 if (!(caps.PixelShaderVersion & 0xffff))
5986 skip("No pixel shader support, skipping tests.\n");
5987 IDirect3DDevice9_Release(device);
5988 IDirect3D9_Release(d3d);
5989 DestroyWindow(window);
5990 return;
5993 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
5994 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5995 ok(!!shader, "Got unexpected shader %p.\n", shader);
5997 /* SetPixelShader() should not touch the shader's refcount. */
5998 i = get_refcount((IUnknown *)shader);
5999 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6000 refcount = get_refcount((IUnknown *)shader);
6001 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6002 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6004 /* GetPixelShader() should increase the shader's refcount by one. */
6005 i = refcount + 1;
6006 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6007 refcount = get_refcount((IUnknown *)shader);
6008 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6009 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6010 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6011 IDirect3DPixelShader9_Release(current_shader);
6013 /* SetPixelShader() with a bogus shader vtbl */
6014 shader_vtbl = shader->lpVtbl;
6015 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6016 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6017 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6018 shader->lpVtbl = NULL;
6019 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6020 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6021 shader->lpVtbl = shader_vtbl;
6023 IDirect3DPixelShader9_Release(shader);
6024 refcount = IDirect3DDevice9_Release(device);
6025 ok(!refcount, "Device has %u references left.\n", refcount);
6026 IDirect3D9_Release(d3d);
6027 DestroyWindow(window);
6030 static void test_pixel_shader_constant(void)
6032 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};
6033 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6034 IDirect3DDevice9 *device;
6035 DWORD consts = 0;
6036 IDirect3D9 *d3d;
6037 ULONG refcount;
6038 D3DCAPS9 caps;
6039 HWND window;
6040 HRESULT hr;
6042 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6043 0, 0, 640, 480, 0, 0, 0, 0);
6044 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6045 ok(!!d3d, "Failed to create a D3D object.\n");
6046 if (!(device = create_device(d3d, window, NULL)))
6048 skip("Failed to create a D3D device, skipping tests.\n");
6049 IDirect3D9_Release(d3d);
6050 DestroyWindow(window);
6051 return;
6054 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6055 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6056 if (!(caps.PixelShaderVersion & 0xffff))
6058 skip("No pixel shader support, skipping tests.\n");
6059 IDirect3DDevice9_Release(device);
6060 IDirect3D9_Release(d3d);
6061 DestroyWindow(window);
6062 return;
6065 /* A simple check that the stuff works at all. */
6066 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6067 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6069 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6070 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6071 consts = consts - 1;
6072 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6074 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6075 * pointless given the way the constant limit was determined. */
6076 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6077 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6079 /* Constant -1. */
6080 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6081 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6083 refcount = IDirect3DDevice9_Release(device);
6084 ok(!refcount, "Device has %u references left.\n", refcount);
6085 IDirect3D9_Release(d3d);
6086 DestroyWindow(window);
6089 static void test_unsupported_shaders(void)
6091 static const DWORD vs_3_0[] =
6093 0xfffe0300, /* vs_3_0 */
6094 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6095 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6096 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6097 0x0000ffff, /* end */
6100 #if 0
6101 float4 main(const float4 color : COLOR) : SV_TARGET
6103 float4 o;
6105 o = color;
6107 return o;
6109 #endif
6110 static const DWORD ps_4_0[] =
6112 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6113 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6114 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6115 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6116 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6117 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6118 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6119 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6120 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6121 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6122 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6123 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6124 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6125 0x00000000, 0x00000000, 0x00000000,
6127 #if 0
6128 vs_1_1
6129 dcl_position v0
6130 def c255, 1.0, 1.0, 1.0, 1.0
6131 add r0, v0, c255
6132 mov oPos, r0
6133 #endif
6134 static const DWORD vs_1_255[] =
6136 0xfffe0101,
6137 0x0000001f, 0x80000000, 0x900f0000,
6138 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6139 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6140 0x00000001, 0xc00f0000, 0x80e40000,
6141 0x0000ffff
6143 #if 0
6144 vs_1_1
6145 dcl_position v0
6146 def c256, 1.0, 1.0, 1.0, 1.0
6147 add r0, v0, c256
6148 mov oPos, r0
6149 #endif
6150 static const DWORD vs_1_256[] =
6152 0xfffe0101,
6153 0x0000001f, 0x80000000, 0x900f0000,
6154 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6155 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6156 0x00000001, 0xc00f0000, 0x80e40000,
6157 0x0000ffff
6159 #if 0
6160 vs_3_0
6161 dcl_position v0
6162 dcl_position o0
6163 def c256, 1.0, 1.0, 1.0, 1.0
6164 add r0, v0, c256
6165 mov o0, r0
6166 #endif
6167 static const DWORD vs_3_256[] =
6169 0xfffe0300,
6170 0x0200001f, 0x80000000, 0x900f0000,
6171 0x0200001f, 0x80000000, 0xe00f0000,
6172 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6173 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6174 0x02000001, 0xe00f0000, 0x80e40000,
6175 0x0000ffff
6177 #if 0
6178 /* This shader source generates syntax errors with the native shader assembler
6179 * due to the constant register index values.
6180 * The bytecode was modified by hand to use the intended values. */
6181 vs_3_0
6182 dcl_position v0
6183 dcl_position o0
6184 defi i16, 1, 1, 1, 1
6185 rep i16
6186 add r0, r0, v0
6187 endrep
6188 mov o0, r0
6189 #endif
6190 static const DWORD vs_3_i16[] =
6192 0xfffe0300,
6193 0x0200001f, 0x80000000, 0x900f0000,
6194 0x0200001f, 0x80000000, 0xe00f0000,
6195 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6196 0x01000026, 0xf0e40010,
6197 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6198 0x00000027,
6199 0x02000001, 0xe00f0000, 0x80e40000,
6200 0x0000ffff
6202 #if 0
6203 /* This shader source generates syntax errors with the native shader assembler
6204 * due to the constant register index values.
6205 * The bytecode was modified by hand to use the intended values. */
6206 vs_3_0
6207 dcl_position v0
6208 dcl_position o0
6209 defb b16, true
6210 mov r0, v0
6211 if b16
6212 add r0, r0, v0
6213 endif
6214 mov o0, r0
6215 #endif
6216 static const DWORD vs_3_b16[] =
6218 0xfffe0300,
6219 0x0200001f, 0x80000000, 0x900f0000,
6220 0x0200001f, 0x80000000, 0xe00f0000,
6221 0x0200002f, 0xe00f0810, 0x00000001,
6222 0x02000001, 0x800f0000, 0x90e40000,
6223 0x01000028, 0xe0e40810,
6224 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6225 0x0000002b,
6226 0x02000001, 0xe00f0000, 0x80e40000,
6227 0x0000ffff
6229 #if 0
6230 /* This shader source generates syntax errors with the native shader assembler
6231 * due to the constant register index values.
6232 * The bytecode was modified by hand to use the intended values. */
6233 ps_1_1
6234 def c8, 1.0, 1.0, 1.0, 1.0
6235 add r0, v0, c8
6236 #endif
6237 static const DWORD ps_1_8[] =
6239 0xffff0101,
6240 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6241 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6242 0x0000ffff
6244 #if 0
6245 /* This shader source generates syntax errors with the native shader assembler
6246 * due to the constant register index values.
6247 * The bytecode was modified by hand to use the intended values. */
6248 ps_2_0
6249 def c32, 1.0, 1.0, 1.0, 1.0
6250 add oC0, v0, c32
6251 #endif
6252 static const DWORD ps_2_32[] =
6254 0xffff0200,
6255 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6256 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6257 0x0000ffff
6259 #if 0
6260 /* This shader source generates syntax errors with the native shader assembler
6261 * due to the constant register index values.
6262 * The bytecode was modified by hand to use the intended values. */
6263 ps_3_0
6264 dcl_color0 v0
6265 def c224, 1.0, 1.0, 1.0, 1.0
6266 add oC0, v0, c224
6267 #endif
6268 static const DWORD ps_3_224[] =
6270 0xffff0300,
6271 0x0200001f, 0x8000000a, 0x900f0000,
6272 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6273 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6274 0x0000ffff
6276 #if 0
6277 /* This shader source generates syntax errors with the native shader assembler
6278 * due to the constant register index values.
6279 * The bytecode was modified by hand to use the intended values. */
6280 ps_2_0
6281 defb b0, true
6282 defi i0, 1, 1, 1, 1
6283 rep i0
6284 if b0
6285 add r0, r0, v0
6286 endif
6287 endrep
6288 mov oC0, r0
6289 #endif
6290 static const DWORD ps_2_0_boolint[] =
6292 0xffff0200,
6293 0x0200002f, 0xe00f0800, 0x00000001,
6294 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6295 0x01000026, 0xf0e40000,
6296 0x01000028, 0xe0e40800,
6297 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6298 0x0000002b,
6299 0x00000027,
6300 0x02000001, 0x800f0800, 0x80e40000,
6301 0x0000ffff
6304 IDirect3DVertexShader9 *vs = NULL;
6305 IDirect3DPixelShader9 *ps = NULL;
6306 IDirect3DDevice9 *device;
6307 IDirect3D9 * d3d;
6308 ULONG refcount;
6309 D3DCAPS9 caps;
6310 HWND window;
6311 HRESULT hr;
6313 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6314 0, 0, 640, 480, 0, 0, 0, 0);
6315 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6316 ok(!!d3d, "Failed to create a D3D object.\n");
6317 if (!(device = create_device(d3d, window, NULL)))
6319 skip("Failed to create a D3D device, skipping tests.\n");
6320 IDirect3D9_Release(d3d);
6321 DestroyWindow(window);
6322 return;
6325 /* These should always fail, regardless of supported shader version. */
6326 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6327 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6328 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6329 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6330 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6331 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6333 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6334 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6335 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6337 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6338 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6339 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6341 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6342 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6344 else
6346 skip("GPU supports SM2+, skipping SM1 test.\n");
6349 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6351 else
6353 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6355 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6356 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6357 IDirect3DVertexShader9_Release(vs);
6358 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6359 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6360 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6361 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6362 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6363 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6364 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6365 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6368 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6370 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6371 goto cleanup;
6373 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6374 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6375 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6376 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6377 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6378 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6379 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6380 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6381 if (ps)
6382 IDirect3DPixelShader9_Release(ps);
6384 cleanup:
6385 refcount = IDirect3DDevice9_Release(device);
6386 ok(!refcount, "Device has %u references left.\n", refcount);
6387 IDirect3D9_Release(d3d);
6388 DestroyWindow(window);
6391 /* Test the default texture stage state values */
6392 static void test_texture_stage_states(void)
6394 IDirect3DDevice9 *device;
6395 IDirect3D9 *d3d;
6396 unsigned int i;
6397 ULONG refcount;
6398 D3DCAPS9 caps;
6399 DWORD value;
6400 HWND window;
6401 HRESULT hr;
6403 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6404 0, 0, 640, 480, 0, 0, 0, 0);
6405 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6406 ok(!!d3d, "Failed to create a D3D object.\n");
6407 if (!(device = create_device(d3d, window, NULL)))
6409 skip("Failed to create a D3D device, skipping tests.\n");
6410 IDirect3D9_Release(d3d);
6411 DestroyWindow(window);
6412 return;
6415 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6416 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6418 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6420 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6421 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6422 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6423 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6424 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6425 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6426 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6427 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6428 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6429 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6430 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6431 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6432 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6433 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6434 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6435 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6436 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6437 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6438 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6439 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6440 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6441 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6442 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6443 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6444 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6445 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6446 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6447 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6448 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6449 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6450 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6451 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6452 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6453 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6454 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6455 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6456 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6457 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6458 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6459 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6460 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6461 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6462 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6463 ok(value == D3DTTFF_DISABLE,
6464 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6465 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6466 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6467 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6468 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6469 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6470 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6471 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6472 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6473 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6474 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6475 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6476 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6479 refcount = IDirect3DDevice9_Release(device);
6480 ok(!refcount, "Device has %u references left.\n", refcount);
6481 IDirect3D9_Release(d3d);
6482 DestroyWindow(window);
6485 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6487 IDirect3DCubeTexture9 *texture;
6488 IDirect3D9 *d3d;
6489 HRESULT hr;
6491 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6492 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6493 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6494 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6495 IDirect3D9_Release(d3d);
6496 if (FAILED(hr))
6498 skip("No cube mipmap generation support, skipping tests.\n");
6499 return;
6502 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6503 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6504 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6505 IDirect3DCubeTexture9_Release(texture);
6507 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6508 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6509 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6510 IDirect3DCubeTexture9_Release(texture);
6513 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6515 IDirect3DCubeTexture9 *texture;
6516 IDirect3DSurface9 *surface;
6517 D3DSURFACE_DESC desc;
6518 DWORD levels;
6519 HRESULT hr;
6520 D3DCAPS9 caps;
6522 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6523 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6524 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6525 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6527 skip("Failed to create cube texture, skipping tests.\n");
6528 return;
6531 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6532 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6533 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6534 else
6535 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6537 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6538 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6539 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6540 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6541 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6542 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6544 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6545 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6546 IDirect3DSurface9_Release(surface);
6547 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6548 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6549 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6550 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6552 IDirect3DCubeTexture9_Release(texture);
6555 static void test_cube_textures(void)
6557 IDirect3DCubeTexture9 *texture;
6558 IDirect3DDevice9 *device;
6559 IDirect3D9 *d3d;
6560 ULONG refcount;
6561 D3DCAPS9 caps;
6562 HWND window;
6563 HRESULT hr;
6565 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6566 0, 0, 640, 480, 0, 0, 0, 0);
6567 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6568 ok(!!d3d, "Failed to create a D3D object.\n");
6569 if (!(device = create_device(d3d, window, NULL)))
6571 skip("Failed to create a D3D device, skipping tests.\n");
6572 IDirect3D9_Release(d3d);
6573 DestroyWindow(window);
6574 return;
6577 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6578 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6580 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
6582 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6583 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
6584 IDirect3DCubeTexture9_Release(texture);
6585 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6586 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
6587 IDirect3DCubeTexture9_Release(texture);
6588 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6589 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
6590 IDirect3DCubeTexture9_Release(texture);
6592 else
6594 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6595 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
6596 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6597 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
6598 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6599 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
6601 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
6602 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
6603 IDirect3DCubeTexture9_Release(texture);
6605 test_cube_texture_mipmap_gen(device);
6606 test_cube_texture_levels(device);
6608 refcount = IDirect3DDevice9_Release(device);
6609 ok(!refcount, "Device has %u references left.\n", refcount);
6610 IDirect3D9_Release(d3d);
6611 DestroyWindow(window);
6614 static void test_mipmap_gen(void)
6616 D3DTEXTUREFILTERTYPE filter_type;
6617 IDirect3DTexture9 *texture;
6618 IDirect3DSurface9 *surface;
6619 IDirect3DDevice9 *device;
6620 D3DSURFACE_DESC desc;
6621 D3DLOCKED_RECT lr;
6622 IDirect3D9 *d3d;
6623 ULONG refcount;
6624 unsigned int i;
6625 DWORD levels;
6626 HWND window;
6627 HRESULT hr;
6629 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6630 ok(!!d3d, "Failed to create a D3D object.\n");
6632 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6633 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
6635 skip("No mipmap generation support, skipping tests.\n");
6636 IDirect3D9_Release(d3d);
6637 return;
6640 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6641 0, 0, 640, 480, 0, 0, 0, 0);
6642 if (!(device = create_device(d3d, window, NULL)))
6644 skip("Failed to create a D3D device, skipping tests.\n");
6645 IDirect3D9_Release(d3d);
6646 DestroyWindow(window);
6647 return;
6650 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6651 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6652 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6653 IDirect3DTexture9_Release(texture);
6655 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6656 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6657 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6659 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6660 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
6661 "Got unexpected filter_type %#x.\n", filter_type);
6662 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
6663 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6664 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
6665 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6666 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6667 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
6668 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
6669 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6671 levels = IDirect3DTexture9_GetLevelCount(texture);
6672 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6674 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
6676 surface = NULL;
6677 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
6678 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6679 if (surface)
6680 IDirect3DSurface9_Release(surface);
6682 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
6683 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6685 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
6686 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6687 if (SUCCEEDED(hr))
6689 hr = IDirect3DTexture9_UnlockRect(texture, i);
6690 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
6693 IDirect3DTexture9_Release(texture);
6695 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
6696 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6697 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6698 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
6699 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6700 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6702 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
6703 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6704 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6705 levels = IDirect3DTexture9_GetLevelCount(texture);
6706 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6707 IDirect3DTexture9_Release(texture);
6709 refcount = IDirect3DDevice9_Release(device);
6710 ok(!refcount, "Device has %u references left.\n", refcount);
6711 IDirect3D9_Release(d3d);
6712 DestroyWindow(window);
6715 static void test_filter(void)
6717 static const struct
6719 DWORD magfilter, minfilter, mipfilter;
6720 BOOL has_texture;
6721 HRESULT result;
6723 tests[] =
6725 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6726 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6727 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6728 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
6729 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
6731 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6732 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6733 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
6734 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
6736 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6737 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6738 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
6739 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
6740 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
6742 IDirect3DTexture9 *texture;
6743 IDirect3DDevice9 *device;
6744 IDirect3D9 *d3d;
6745 unsigned int i;
6746 ULONG refcount;
6747 DWORD passes;
6748 HWND window;
6749 HRESULT hr;
6751 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6752 ok(!!d3d, "Failed to create a D3D object.\n");
6754 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6755 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6757 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
6758 IDirect3D9_Release(d3d);
6759 return;
6762 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6763 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6765 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
6766 IDirect3D9_Release(d3d);
6767 return;
6770 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6771 0, 0, 640, 480, 0, 0, 0, 0);
6772 if (!(device = create_device(d3d, window, NULL)))
6774 skip("Failed to create a D3D device, skipping tests.\n");
6775 IDirect3D9_Release(d3d);
6776 DestroyWindow(window);
6777 return;
6780 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
6781 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
6782 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6784 /* Needed for ValidateDevice(). */
6785 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6786 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6788 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
6790 if (tests[i].has_texture)
6792 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
6793 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6795 else
6797 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6798 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6801 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
6802 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6803 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
6804 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6805 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
6806 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6808 passes = 0xdeadbeef;
6809 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
6810 ok(hr == tests[i].result,
6811 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
6812 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
6813 tests[i].mipfilter, tests[i].has_texture);
6814 if (SUCCEEDED(hr))
6815 ok(!!passes, "Got unexpected passes %#x.\n", passes);
6816 else
6817 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
6820 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6821 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6822 IDirect3DTexture9_Release(texture);
6824 refcount = IDirect3DDevice9_Release(device);
6825 ok(!refcount, "Device has %u references left.\n", refcount);
6826 IDirect3D9_Release(d3d);
6827 DestroyWindow(window);
6830 static void test_get_set_texture(void)
6832 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
6833 IDirect3DBaseTexture9 *texture;
6834 IDirect3DDevice9 *device;
6835 IDirect3D9 *d3d;
6836 ULONG refcount;
6837 HWND window;
6838 HRESULT hr;
6840 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6841 0, 0, 640, 480, 0, 0, 0, 0);
6842 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6843 ok(!!d3d, "Failed to create a D3D object.\n");
6844 if (!(device = create_device(d3d, window, NULL)))
6846 skip("Failed to create a D3D device, skipping tests.\n");
6847 IDirect3D9_Release(d3d);
6848 DestroyWindow(window);
6849 return;
6852 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
6853 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6854 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6855 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
6856 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6857 ok(!texture, "Got unexpected texture %p.\n", texture);
6859 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
6860 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
6861 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6862 texture_vtbl = texture->lpVtbl;
6863 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
6864 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6865 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6866 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6867 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6868 texture->lpVtbl = NULL;
6869 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6870 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6871 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6872 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6873 texture->lpVtbl = texture_vtbl;
6874 IDirect3DBaseTexture9_Release(texture);
6876 refcount = IDirect3DDevice9_Release(device);
6877 ok(!refcount, "Device has %u references left.\n", refcount);
6878 IDirect3D9_Release(d3d);
6879 DestroyWindow(window);
6882 static void test_lod(void)
6884 IDirect3DTexture9 *texture;
6885 IDirect3DDevice9 *device;
6886 IDirect3D9 *d3d;
6887 ULONG refcount;
6888 HWND window;
6889 HRESULT hr;
6890 DWORD ret;
6892 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6893 0, 0, 640, 480, 0, 0, 0, 0);
6894 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6895 ok(!!d3d, "Failed to create a D3D object.\n");
6896 if (!(device = create_device(d3d, window, NULL)))
6898 skip("Failed to create a D3D device, skipping tests.\n");
6899 IDirect3D9_Release(d3d);
6900 DestroyWindow(window);
6901 return;
6904 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
6905 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6906 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6908 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
6909 * return a HRESULT, so it can't return a normal error. Instead, the call
6910 * is simply ignored. */
6911 ret = IDirect3DTexture9_SetLOD(texture, 0);
6912 ok(!ret, "Got unexpected ret %u.\n", ret);
6913 ret = IDirect3DTexture9_SetLOD(texture, 1);
6914 ok(!ret, "Got unexpected ret %u.\n", ret);
6915 ret = IDirect3DTexture9_SetLOD(texture, 2);
6916 ok(!ret, "Got unexpected ret %u.\n", ret);
6917 ret = IDirect3DTexture9_GetLOD(texture);
6918 ok(!ret, "Got unexpected ret %u.\n", ret);
6920 IDirect3DTexture9_Release(texture);
6921 refcount = IDirect3DDevice9_Release(device);
6922 ok(!refcount, "Device has %u references left.\n", refcount);
6923 IDirect3D9_Release(d3d);
6924 DestroyWindow(window);
6927 static void test_surface_get_container(void)
6929 IDirect3DTexture9 *texture = NULL;
6930 IDirect3DSurface9 *surface = NULL;
6931 IDirect3DDevice9 *device;
6932 IUnknown *container;
6933 IDirect3D9 *d3d;
6934 ULONG refcount;
6935 HWND window;
6936 HRESULT hr;
6938 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6939 0, 0, 640, 480, 0, 0, 0, 0);
6940 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6941 ok(!!d3d, "Failed to create a D3D object.\n");
6942 if (!(device = create_device(d3d, window, NULL)))
6944 skip("Failed to create a D3D device, skipping tests.\n");
6945 IDirect3D9_Release(d3d);
6946 DestroyWindow(window);
6947 return;
6950 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
6951 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6952 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6953 ok(!!texture, "Got unexpected texture %p.\n", texture);
6955 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6956 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
6957 ok(!!surface, "Got unexpected surface %p.\n", surface);
6959 /* These should work... */
6960 container = NULL;
6961 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
6962 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6963 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6964 IUnknown_Release(container);
6966 container = NULL;
6967 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
6968 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6969 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6970 IUnknown_Release(container);
6972 container = NULL;
6973 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
6974 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6975 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6976 IUnknown_Release(container);
6978 container = NULL;
6979 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
6980 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6981 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6982 IUnknown_Release(container);
6984 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
6985 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
6986 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
6987 ok(!container, "Got unexpected container %p.\n", container);
6989 IDirect3DSurface9_Release(surface);
6990 IDirect3DTexture9_Release(texture);
6991 refcount = IDirect3DDevice9_Release(device);
6992 ok(!refcount, "Device has %u references left.\n", refcount);
6993 IDirect3D9_Release(d3d);
6994 DestroyWindow(window);
6997 static void test_surface_alignment(void)
6999 IDirect3DSurface9 *surface;
7000 IDirect3DDevice9 *device;
7001 D3DLOCKED_RECT lr;
7002 unsigned int i, j;
7003 IDirect3D9 *d3d;
7004 ULONG refcount;
7005 HWND window;
7006 HRESULT hr;
7008 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7009 0, 0, 640, 480, 0, 0, 0, 0);
7010 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7011 ok(!!d3d, "Failed to create a D3D object.\n");
7012 if (!(device = create_device(d3d, window, NULL)))
7014 skip("Failed to create a D3D device, skipping tests.\n");
7015 IDirect3D9_Release(d3d);
7016 DestroyWindow(window);
7017 return;
7020 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7021 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7022 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7023 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7025 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7026 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7027 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7028 /* Some applications also depend on the exact pitch, rather than just the
7029 * alignment. */
7030 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7031 hr = IDirect3DSurface9_UnlockRect(surface);
7032 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7033 IDirect3DSurface9_Release(surface);
7035 for (i = 0; i < 5; ++i)
7037 IDirect3DTexture9 *texture;
7038 unsigned int level_count;
7039 D3DSURFACE_DESC desc;
7040 int expected_pitch;
7042 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7043 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7044 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7045 if (FAILED(hr))
7047 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7048 continue;
7051 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7052 for (j = 0; j < level_count; ++j)
7054 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7055 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7056 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7057 hr = IDirect3DTexture9_UnlockRect(texture, j);
7058 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7060 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7061 if (i > 0)
7062 expected_pitch <<= 1;
7063 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7064 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7066 IDirect3DTexture9_Release(texture);
7069 refcount = IDirect3DDevice9_Release(device);
7070 ok(!refcount, "Device has %u references left.\n", refcount);
7071 IDirect3D9_Release(d3d);
7072 DestroyWindow(window);
7075 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7076 * different from regular formats. This test verifies we return the correct
7077 * memory offsets. */
7078 static void test_lockrect_offset(void)
7080 static const struct
7082 D3DFORMAT format;
7083 const char *name;
7084 unsigned int block_width;
7085 unsigned int block_height;
7086 unsigned int block_size;
7088 dxt_formats[] =
7090 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7091 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7092 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7093 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7094 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7095 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7096 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7098 unsigned int expected_offset, offset, i;
7099 const RECT rect = {60, 60, 68, 68};
7100 IDirect3DSurface9 *surface;
7101 D3DLOCKED_RECT locked_rect;
7102 IDirect3DDevice9 *device;
7103 int expected_pitch;
7104 IDirect3D9 *d3d;
7105 ULONG refcount;
7106 HWND window;
7107 BYTE *base;
7108 HRESULT hr;
7110 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7111 0, 0, 640, 480, 0, 0, 0, 0);
7112 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7113 ok(!!d3d, "Failed to create a D3D object.\n");
7114 if (!(device = create_device(d3d, window, NULL)))
7116 skip("Failed to create a D3D device, skipping tests.\n");
7117 IDirect3D9_Release(d3d);
7118 DestroyWindow(window);
7119 return;
7122 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
7124 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7125 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7127 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7128 continue;
7131 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7132 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7133 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7135 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7136 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7138 base = locked_rect.pBits;
7139 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7140 * dxt_formats[i].block_size;
7141 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7142 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7144 hr = IDirect3DSurface9_UnlockRect(surface);
7145 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7147 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7148 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7150 offset = (BYTE *)locked_rect.pBits - base;
7151 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7152 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7153 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7154 offset, dxt_formats[i].name, expected_offset);
7156 hr = IDirect3DSurface9_UnlockRect(surface);
7157 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7159 IDirect3DSurface9_Release(surface);
7162 refcount = IDirect3DDevice9_Release(device);
7163 ok(!refcount, "Device has %u references left.\n", refcount);
7164 IDirect3D9_Release(d3d);
7165 DestroyWindow(window);
7168 static void test_lockrect_invalid(void)
7170 static const struct
7172 RECT rect;
7173 HRESULT win7_result;
7175 test_data[] =
7177 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7178 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7179 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7180 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7181 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7182 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7183 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7184 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7185 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7186 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7187 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7188 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7189 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7191 static const RECT test_rect_2 = {0, 0, 8, 8};
7192 IDirect3DSurface9 *surface = NULL;
7193 D3DLOCKED_RECT locked_rect;
7194 IDirect3DDevice9 *device;
7195 IDirect3DTexture9 *texture;
7196 IDirect3DCubeTexture9 *cube_texture;
7197 IDirect3D9 *d3d;
7198 unsigned int i, r;
7199 ULONG refcount;
7200 HWND window;
7201 BYTE *base;
7202 HRESULT hr;
7203 static const struct
7205 D3DRESOURCETYPE type;
7206 D3DPOOL pool;
7207 const char *name;
7209 resources[] =
7211 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7212 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7213 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7214 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7215 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7216 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7217 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7220 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7221 0, 0, 640, 480, 0, 0, 0, 0);
7222 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7223 ok(!!d3d, "Failed to create a D3D object.\n");
7224 if (!(device = create_device(d3d, window, NULL)))
7226 skip("Failed to create a D3D device, skipping tests.\n");
7227 IDirect3D9_Release(d3d);
7228 DestroyWindow(window);
7229 return;
7232 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
7234 texture = NULL;
7235 cube_texture = NULL;
7236 switch (resources[r].type)
7238 case D3DRTYPE_SURFACE:
7239 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7240 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7241 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7242 hr, resources[r].name);
7243 break;
7245 case D3DRTYPE_TEXTURE:
7246 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7247 resources[r].pool, &texture, NULL);
7248 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7249 hr, resources[r].name);
7250 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7251 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7252 hr, resources[r].name);
7253 break;
7255 case D3DRTYPE_CUBETEXTURE:
7256 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7257 resources[r].pool, &cube_texture, NULL);
7258 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7259 hr, resources[r].name);
7260 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7261 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7262 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7263 hr, resources[r].name);
7264 break;
7266 default:
7267 break;
7270 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7271 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7272 base = locked_rect.pBits;
7273 hr = IDirect3DSurface9_UnlockRect(surface);
7274 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7276 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7278 unsigned int offset, expected_offset;
7279 const RECT *rect = &test_data[i].rect;
7281 locked_rect.pBits = (BYTE *)0xdeadbeef;
7282 locked_rect.Pitch = 0xdeadbeef;
7284 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7285 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7286 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7287 * one broken. */
7288 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7289 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7290 wine_dbgstr_rect(rect), hr, resources[r].name);
7291 if (FAILED(hr))
7292 continue;
7294 offset = (BYTE *)locked_rect.pBits - base;
7295 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7296 ok(offset == expected_offset,
7297 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7298 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7300 hr = IDirect3DSurface9_UnlockRect(surface);
7301 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7303 if (texture)
7305 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7306 ok(SUCCEEDED(hr),
7307 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7308 wine_dbgstr_rect(rect), hr, resources[r].name);
7309 if (FAILED(hr))
7310 continue;
7312 offset = (BYTE *)locked_rect.pBits - base;
7313 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7314 ok(offset == expected_offset,
7315 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7316 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7318 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7319 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7321 if (cube_texture)
7323 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7324 &locked_rect, rect, 0);
7325 ok(SUCCEEDED(hr),
7326 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7327 wine_dbgstr_rect(rect), hr, resources[r].name);
7328 if (FAILED(hr))
7329 continue;
7331 offset = (BYTE *)locked_rect.pBits - base;
7332 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7333 ok(offset == expected_offset,
7334 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7335 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7337 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7338 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7342 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7343 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7344 locked_rect.pBits = (BYTE *)0xdeadbeef;
7345 locked_rect.Pitch = 1;
7346 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7347 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7348 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7349 locked_rect.pBits, resources[r].name);
7350 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7351 locked_rect.Pitch, resources[r].name);
7352 hr = IDirect3DSurface9_UnlockRect(surface);
7353 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7355 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7356 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7357 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7358 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7359 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7360 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7361 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7362 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7363 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7364 hr = IDirect3DSurface9_UnlockRect(surface);
7365 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7367 IDirect3DSurface9_Release(surface);
7369 if (texture)
7371 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7372 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7373 hr, resources[r].name);
7374 locked_rect.pBits = (BYTE *)0xdeadbeef;
7375 locked_rect.Pitch = 1;
7376 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7377 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7378 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7379 locked_rect.pBits, resources[r].name);
7380 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7381 locked_rect.Pitch, resources[r].name);
7382 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7383 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7384 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7385 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7387 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7388 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7389 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7390 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7391 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7392 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7393 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7394 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7395 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7396 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7397 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7399 IDirect3DTexture9_Release(texture);
7401 if (cube_texture)
7403 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7404 &locked_rect, NULL, 0);
7405 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7406 hr, resources[r].name);
7407 locked_rect.pBits = (BYTE *)0xdeadbeef;
7408 locked_rect.Pitch = 1;
7409 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7410 &locked_rect, NULL, 0);
7411 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7412 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7413 locked_rect.pBits, resources[r].name);
7414 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7415 locked_rect.Pitch, resources[r].name);
7416 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7417 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7418 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7419 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7421 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7422 &locked_rect, &test_data[0].rect, 0);
7423 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7424 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7425 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7426 &locked_rect, &test_data[0].rect, 0);
7427 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7428 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7429 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7430 &locked_rect, &test_rect_2, 0);
7431 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7432 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7433 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7434 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7436 IDirect3DCubeTexture9_Release(cube_texture);
7440 refcount = IDirect3DDevice9_Release(device);
7441 ok(!refcount, "Device has %u references left.\n", refcount);
7442 IDirect3D9_Release(d3d);
7443 DestroyWindow(window);
7446 static void test_private_data(void)
7448 ULONG refcount, expected_refcount;
7449 IDirect3DTexture9 *texture;
7450 IDirect3DSurface9 *surface, *surface2;
7451 IDirect3DDevice9 *device;
7452 IDirect3D9 *d3d;
7453 IUnknown *ptr;
7454 HWND window;
7455 HRESULT hr;
7456 DWORD size;
7457 DWORD data[4] = {1, 2, 3, 4};
7458 static const GUID d3d9_private_data_test_guid2 =
7460 0x2e5afac2,
7461 0x87b5,
7462 0x4c10,
7463 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7466 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7467 0, 0, 640, 480, 0, 0, 0, 0);
7468 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7469 ok(!!d3d, "Failed to create a D3D object.\n");
7470 if (!(device = create_device(d3d, window, NULL)))
7472 skip("Failed to create a D3D device, skipping tests.\n");
7473 IDirect3D9_Release(d3d);
7474 DestroyWindow(window);
7475 return;
7478 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7479 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7480 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7482 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7483 device, 0, D3DSPD_IUNKNOWN);
7484 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7485 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7486 device, 5, D3DSPD_IUNKNOWN);
7487 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7488 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7489 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7490 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7492 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7493 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7494 sizeof(device), D3DSPD_IUNKNOWN);
7495 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7496 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7497 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7498 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7499 size = sizeof(ptr);
7500 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7501 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7502 IUnknown_Release(ptr);
7503 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7504 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7506 refcount = get_refcount((IUnknown *)device);
7507 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7508 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7509 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7510 expected_refcount = refcount + 1;
7511 refcount = get_refcount((IUnknown *)device);
7512 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7513 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7514 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7515 expected_refcount = refcount - 1;
7516 refcount = get_refcount((IUnknown *)device);
7517 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7519 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7520 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7521 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7522 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7523 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7524 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7525 refcount = get_refcount((IUnknown *)device);
7526 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7528 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7529 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7530 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7531 size = 2 * sizeof(ptr);
7532 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7533 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7534 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7535 expected_refcount = refcount + 2;
7536 refcount = get_refcount((IUnknown *)device);
7537 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7538 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
7539 IUnknown_Release(ptr);
7540 expected_refcount--;
7542 ptr = (IUnknown *)0xdeadbeef;
7543 size = 1;
7544 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7545 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7546 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7547 size = 2 * sizeof(ptr);
7548 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7549 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7550 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7551 refcount = get_refcount((IUnknown *)device);
7552 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7553 size = 1;
7554 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7555 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7556 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7557 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7558 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
7559 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7560 size = 0xdeadbabe;
7561 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
7562 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7563 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7564 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7565 /* GetPrivateData with size = NULL causes an access violation on Windows if the
7566 * requested data exists. */
7568 /* Destroying the surface frees the held reference. */
7569 IDirect3DSurface9_Release(surface);
7570 expected_refcount = refcount - 2;
7571 refcount = get_refcount((IUnknown *)device);
7572 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7574 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
7575 &texture, NULL);
7576 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7577 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7578 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
7579 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
7580 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
7582 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7583 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7585 memset(data, 0, sizeof(data));
7586 size = sizeof(data);
7587 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
7588 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7589 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
7590 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7591 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
7592 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
7594 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
7595 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7597 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7598 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7599 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
7600 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7602 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7603 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7605 IDirect3DSurface9_Release(surface2);
7606 IDirect3DSurface9_Release(surface);
7607 IDirect3DTexture9_Release(texture);
7609 refcount = IDirect3DDevice9_Release(device);
7610 ok(!refcount, "Device has %u references left.\n", refcount);
7611 IDirect3D9_Release(d3d);
7612 DestroyWindow(window);
7615 static void test_getdc(void)
7617 static const struct
7619 const char *name;
7620 D3DFORMAT format;
7621 unsigned int bit_count;
7622 DWORD mask_r, mask_g, mask_b;
7623 BOOL getdc_supported;
7625 testdata[] =
7627 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7628 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7629 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
7630 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7631 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7632 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
7633 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7634 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7635 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7636 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7637 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7638 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7639 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7640 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7641 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7642 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
7643 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7644 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7645 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7646 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7648 IDirect3DSurface9 *surface, *surface2;
7649 IDirect3DCubeTexture9 *cube_texture;
7650 IDirect3DTexture9 *texture;
7651 IDirect3DDevice9 *device;
7652 D3DLOCKED_RECT map_desc;
7653 IDirect3D9 *d3d;
7654 unsigned int i;
7655 ULONG refcount;
7656 HWND window;
7657 HDC dc, dc2;
7658 HRESULT hr;
7660 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7661 0, 0, 640, 480, 0, 0, 0, 0);
7662 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7663 ok(!!d3d, "Failed to create a D3D object.\n");
7664 if (!(device = create_device(d3d, window, NULL)))
7666 skip("Failed to create a D3D device, skipping tests.\n");
7667 IDirect3D9_Release(d3d);
7668 DestroyWindow(window);
7669 return;
7672 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
7674 texture = NULL;
7675 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7676 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
7677 if (FAILED(hr))
7679 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
7680 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
7681 if (FAILED(hr))
7683 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7684 continue;
7686 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7687 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7690 dc = (void *)0x1234;
7691 hr = IDirect3DSurface9_GetDC(surface, &dc);
7692 if (testdata[i].getdc_supported)
7693 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7694 else
7695 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7697 if (SUCCEEDED(hr))
7699 unsigned int width_bytes;
7700 DIBSECTION dib;
7701 HBITMAP bitmap;
7702 DWORD type;
7703 int size;
7705 type = GetObjectType(dc);
7706 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7707 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7708 type = GetObjectType(bitmap);
7709 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7711 size = GetObjectA(bitmap, sizeof(dib), &dib);
7712 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
7713 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
7714 dib.dsBm.bmType, testdata[i].name);
7715 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
7716 dib.dsBm.bmWidth, testdata[i].name);
7717 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
7718 dib.dsBm.bmHeight, testdata[i].name);
7719 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
7720 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
7721 dib.dsBm.bmWidthBytes, testdata[i].name);
7722 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
7723 dib.dsBm.bmPlanes, testdata[i].name);
7724 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
7725 "Got unexpected bit count %d for format %s.\n",
7726 dib.dsBm.bmBitsPixel, testdata[i].name);
7727 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
7728 dib.dsBm.bmBits, testdata[i].name);
7730 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
7731 dib.dsBmih.biSize, testdata[i].name);
7732 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
7733 dib.dsBmih.biHeight, testdata[i].name);
7734 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
7735 dib.dsBmih.biHeight, testdata[i].name);
7736 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
7737 dib.dsBmih.biPlanes, testdata[i].name);
7738 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
7739 dib.dsBmih.biBitCount, testdata[i].name);
7740 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
7741 "Got unexpected compression %#x for format %s.\n",
7742 dib.dsBmih.biCompression, testdata[i].name);
7743 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
7744 dib.dsBmih.biSizeImage, testdata[i].name);
7745 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
7746 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
7747 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
7748 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
7749 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
7750 dib.dsBmih.biClrUsed, testdata[i].name);
7751 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
7752 dib.dsBmih.biClrImportant, testdata[i].name);
7754 if (dib.dsBmih.biCompression == BI_BITFIELDS)
7756 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
7757 && dib.dsBitfields[2] == testdata[i].mask_b,
7758 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7759 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7761 else
7763 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
7764 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7765 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7767 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
7768 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
7770 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7771 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
7773 else
7775 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
7778 IDirect3DSurface9_Release(surface);
7779 if (texture)
7780 IDirect3DTexture9_Release(texture);
7782 if (!testdata[i].getdc_supported)
7783 continue;
7785 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
7786 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
7788 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7789 continue;
7792 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
7793 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7794 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
7795 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7797 hr = IDirect3DSurface9_GetDC(surface, &dc);
7798 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7799 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7800 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7801 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7802 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7803 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7804 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7806 hr = IDirect3DSurface9_GetDC(surface, &dc);
7807 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7808 dc2 = (void *)0x1234;
7809 hr = IDirect3DSurface9_GetDC(surface, &dc2);
7810 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7811 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
7812 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7813 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7814 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7815 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7817 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7818 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7819 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7820 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7821 hr = IDirect3DSurface9_UnlockRect(surface);
7822 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7823 hr = IDirect3DSurface9_UnlockRect(surface);
7824 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7826 hr = IDirect3DSurface9_GetDC(surface, &dc);
7827 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7828 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7829 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7830 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7831 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7833 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7834 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7835 hr = IDirect3DSurface9_GetDC(surface, &dc);
7836 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7837 hr = IDirect3DSurface9_UnlockRect(surface);
7838 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7840 hr = IDirect3DSurface9_GetDC(surface, &dc);
7841 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7842 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
7843 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7844 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
7845 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7846 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7847 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7849 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7850 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7851 hr = IDirect3DSurface9_GetDC(surface, &dc2);
7852 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7853 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
7854 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7855 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7856 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7858 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7859 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7860 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7861 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7862 hr = IDirect3DSurface9_UnlockRect(surface2);
7863 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7864 hr = IDirect3DSurface9_UnlockRect(surface);
7865 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7867 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7868 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7869 hr = IDirect3DSurface9_GetDC(surface, &dc);
7870 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7871 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7872 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7873 hr = IDirect3DSurface9_UnlockRect(surface);
7874 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7876 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7877 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7878 hr = IDirect3DSurface9_GetDC(surface, &dc);
7879 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7880 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7881 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7882 hr = IDirect3DSurface9_UnlockRect(surface2);
7883 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7885 hr = IDirect3DSurface9_GetDC(surface, &dc);
7886 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7887 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7888 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7889 hr = IDirect3DSurface9_UnlockRect(surface2);
7890 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7891 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7892 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7894 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7895 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7896 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7897 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7898 hr = IDirect3DSurface9_UnlockRect(surface);
7899 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7900 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7901 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7903 hr = IDirect3DSurface9_UnlockRect(surface);
7904 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7905 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7906 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7907 hr = IDirect3DSurface9_UnlockRect(surface);
7908 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7909 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7910 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7911 hr = IDirect3DSurface9_UnlockRect(surface);
7912 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7914 hr = IDirect3DSurface9_UnlockRect(surface2);
7915 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7916 hr = IDirect3DSurface9_GetDC(surface, &dc);
7917 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7918 hr = IDirect3DSurface9_UnlockRect(surface2);
7919 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7920 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7921 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7922 hr = IDirect3DSurface9_UnlockRect(surface2);
7923 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7925 IDirect3DSurface9_Release(surface2);
7926 IDirect3DSurface9_Release(surface);
7927 IDirect3DCubeTexture9_Release(cube_texture);
7930 refcount = IDirect3DDevice9_Release(device);
7931 ok(!refcount, "Device has %u references left.\n", refcount);
7932 IDirect3D9_Release(d3d);
7933 DestroyWindow(window);
7936 static void test_surface_dimensions(void)
7938 IDirect3DSurface9 *surface;
7939 IDirect3DDevice9 *device;
7940 IDirect3D9 *d3d;
7941 ULONG refcount;
7942 HWND window;
7943 HRESULT hr;
7945 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7946 0, 0, 640, 480, 0, 0, 0, 0);
7947 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7948 ok(!!d3d, "Failed to create a D3D object.\n");
7949 if (!(device = create_device(d3d, window, NULL)))
7951 skip("Failed to create a D3D device, skipping tests.\n");
7952 IDirect3D9_Release(d3d);
7953 DestroyWindow(window);
7954 return;
7957 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
7958 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7959 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7960 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
7961 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7962 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7964 refcount = IDirect3DDevice9_Release(device);
7965 ok(!refcount, "Device has %u references left.\n", refcount);
7966 IDirect3D9_Release(d3d);
7967 DestroyWindow(window);
7970 static void test_surface_format_null(void)
7972 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
7973 IDirect3DTexture9 *texture;
7974 IDirect3DSurface9 *surface;
7975 IDirect3DSurface9 *rt, *ds;
7976 D3DLOCKED_RECT locked_rect;
7977 IDirect3DDevice9 *device;
7978 D3DSURFACE_DESC desc;
7979 IDirect3D9 *d3d;
7980 ULONG refcount;
7981 HWND window;
7982 HRESULT hr;
7984 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7985 ok(!!d3d, "Failed to create a D3D object.\n");
7987 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7988 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
7989 if (hr != D3D_OK)
7991 skip("No D3DFMT_NULL support, skipping test.\n");
7992 IDirect3D9_Release(d3d);
7993 return;
7996 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7997 0, 0, 640, 480, 0, 0, 0, 0);
7998 if (!(device = create_device(d3d, window, NULL)))
8000 skip("Failed to create a D3D device, skipping tests.\n");
8001 IDirect3D9_Release(d3d);
8002 DestroyWindow(window);
8003 return;
8006 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8007 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8008 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8010 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8011 D3DFMT_NULL, D3DFMT_D24S8);
8012 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8014 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8015 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8016 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8018 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8019 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8021 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8022 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8024 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8025 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8027 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8028 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8030 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8031 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8033 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8034 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8036 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8037 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8039 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8040 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8042 IDirect3DSurface9_Release(rt);
8043 IDirect3DSurface9_Release(ds);
8045 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8046 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8047 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8048 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8050 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8051 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8052 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8053 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8055 hr = IDirect3DSurface9_UnlockRect(surface);
8056 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8058 IDirect3DSurface9_Release(surface);
8060 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8061 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8062 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8063 IDirect3DTexture9_Release(texture);
8065 refcount = IDirect3DDevice9_Release(device);
8066 ok(!refcount, "Device has %u references left.\n", refcount);
8067 IDirect3D9_Release(d3d);
8068 DestroyWindow(window);
8071 static void test_surface_double_unlock(void)
8073 static const D3DPOOL pools[] =
8075 D3DPOOL_DEFAULT,
8076 D3DPOOL_SCRATCH,
8077 D3DPOOL_SYSTEMMEM,
8079 IDirect3DSurface9 *surface;
8080 IDirect3DDevice9 *device;
8081 D3DLOCKED_RECT lr;
8082 IDirect3D9 *d3d;
8083 unsigned int i;
8084 ULONG refcount;
8085 HWND window;
8086 HRESULT hr;
8088 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8089 0, 0, 640, 480, 0, 0, 0, 0);
8090 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8091 ok(!!d3d, "Failed to create a D3D object.\n");
8092 if (!(device = create_device(d3d, window, NULL)))
8094 skip("Failed to create a D3D device, skipping tests.\n");
8095 IDirect3D9_Release(d3d);
8096 DestroyWindow(window);
8097 return;
8100 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
8102 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8103 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8104 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8106 hr = IDirect3DSurface9_UnlockRect(surface);
8107 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8108 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8109 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8110 hr = IDirect3DSurface9_UnlockRect(surface);
8111 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8112 hr = IDirect3DSurface9_UnlockRect(surface);
8113 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8115 IDirect3DSurface9_Release(surface);
8118 refcount = IDirect3DDevice9_Release(device);
8119 ok(!refcount, "Device has %u references left.\n", refcount);
8120 IDirect3D9_Release(d3d);
8121 DestroyWindow(window);
8124 static void test_surface_blocks(void)
8126 static const struct
8128 D3DFORMAT fmt;
8129 const char *name;
8130 unsigned int block_width;
8131 unsigned int block_height;
8132 BOOL broken;
8133 BOOL create_size_checked, core_fmt;
8135 formats[] =
8137 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8138 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8139 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8140 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8141 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8142 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8143 * which doesn't match the format spec. On newer Nvidia cards
8144 * they have the correct 4x4 block size */
8145 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8146 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8147 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8148 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8150 static const struct
8152 D3DPOOL pool;
8153 const char *name;
8154 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8155 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8156 BOOL success;
8158 pools[] =
8160 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8161 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8162 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8163 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8165 static struct
8167 D3DRESOURCETYPE rtype;
8168 const char *type_name;
8169 D3DPOOL pool;
8170 const char *pool_name;
8171 BOOL need_driver_support, need_runtime_support;
8173 create_tests[] =
8175 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8176 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8177 /* Managed offscreen plain surfaces are not supported */
8178 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8180 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8181 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8182 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8183 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8185 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8186 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8187 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8188 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8190 IDirect3DTexture9 *texture;
8191 IDirect3DCubeTexture9 *cube_texture;
8192 IDirect3DSurface9 *surface;
8193 D3DLOCKED_RECT locked_rect;
8194 IDirect3DDevice9 *device;
8195 unsigned int i, j, k, w, h;
8196 BOOL surface_only;
8197 IDirect3D9 *d3d;
8198 ULONG refcount;
8199 HWND window;
8200 HRESULT hr;
8201 RECT rect;
8202 BOOL tex_pow2, cube_pow2;
8203 D3DCAPS9 caps;
8204 static const RECT invalid[] =
8206 {60, 60, 60, 68}, /* 0 height */
8207 {60, 60, 68, 60}, /* 0 width */
8208 {68, 60, 60, 68}, /* left > right */
8209 {60, 68, 68, 60}, /* top > bottom */
8210 {-8, 60, 0, 68}, /* left < surface */
8211 {60, -8, 68, 0}, /* top < surface */
8212 {-16, 60, -8, 68}, /* right < surface */
8213 {60, -16, 68, -8}, /* bottom < surface */
8214 {60, 60, 136, 68}, /* right > surface */
8215 {60, 60, 68, 136}, /* bottom > surface */
8216 {136, 60, 144, 68}, /* left > surface */
8217 {60, 136, 68, 144}, /* top > surface */
8220 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8221 0, 0, 640, 480, 0, 0, 0, 0);
8222 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8223 ok(!!d3d, "Failed to create a D3D object.\n");
8224 if (!(device = create_device(d3d, window, NULL)))
8226 skip("Failed to create a D3D device, skipping tests.\n");
8227 IDirect3D9_Release(d3d);
8228 DestroyWindow(window);
8229 return;
8232 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8233 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8234 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8235 if (tex_pow2)
8236 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8237 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8239 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
8241 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8243 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8244 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8245 tex_support = SUCCEEDED(hr);
8246 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8247 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8248 cube_support = SUCCEEDED(hr);
8249 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8250 0, D3DRTYPE_SURFACE, formats[i].fmt);
8251 surface_support = SUCCEEDED(hr);
8253 /* Scratch pool in general allows texture creation even if the driver does
8254 * not support the format. If the format is an extension format that is not
8255 * known to the runtime, like ATI2N, some driver support is required for
8256 * this to work.
8258 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8259 * about ATI2N. I cannot check this because all my Vista+ machines support
8260 * ATI2N in hardware, but none of my WinXP machines do. */
8261 format_known = tex_support || cube_support || surface_support;
8263 for (w = 1; w <= 8; w++)
8265 for (h = 1; h <= 8; h++)
8267 BOOL block_aligned = TRUE;
8268 BOOL size_is_pow2;
8270 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8271 block_aligned = FALSE;
8273 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8275 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
8277 BOOL support, pow2;
8278 HRESULT expect_hr;
8279 BOOL may_succeed = FALSE;
8280 IUnknown **check_null;
8282 if (!formats[i].core_fmt)
8284 /* AMD warns against creating ATI2N textures smaller than
8285 * the block size because the runtime cannot calculate the
8286 * correct texture size. Generalize this for all extension
8287 * formats. */
8288 if (w < formats[i].block_width || h < formats[i].block_height)
8289 continue;
8292 texture = (IDirect3DTexture9 *)0xdeadbeef;
8293 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8294 surface = (IDirect3DSurface9 *)0xdeadbeef;
8296 switch (create_tests[j].rtype)
8298 case D3DRTYPE_TEXTURE:
8299 check_null = (IUnknown **)&texture;
8300 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8301 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8302 support = tex_support;
8303 pow2 = tex_pow2;
8304 break;
8306 case D3DRTYPE_CUBETEXTURE:
8307 if (w != h)
8308 continue;
8309 check_null = (IUnknown **)&cube_texture;
8310 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8311 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8312 support = cube_support;
8313 pow2 = cube_pow2;
8314 break;
8316 case D3DRTYPE_SURFACE:
8317 check_null = (IUnknown **)&surface;
8318 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8319 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8320 support = surface_support;
8321 pow2 = FALSE;
8322 break;
8324 default:
8325 check_null = NULL;
8326 pow2 = FALSE;
8327 support = FALSE;
8328 break;
8331 if (create_tests[j].need_driver_support && !support)
8332 expect_hr = D3DERR_INVALIDCALL;
8333 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8334 expect_hr = D3DERR_INVALIDCALL;
8335 else if (formats[i].create_size_checked && !block_aligned)
8336 expect_hr = D3DERR_INVALIDCALL;
8337 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8338 expect_hr = D3DERR_INVALIDCALL;
8339 else
8340 expect_hr = D3D_OK;
8342 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8343 * does not support it. Accept scratch creation of extension formats on
8344 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8345 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8346 * support it. */
8347 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8348 may_succeed = TRUE;
8350 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8351 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8352 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8353 if (FAILED(hr))
8354 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8355 else
8356 IUnknown_Release(*check_null);
8361 surface_only = FALSE;
8362 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8363 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8364 dynamic_tex_support = SUCCEEDED(hr);
8365 if (!dynamic_tex_support)
8367 if (!surface_support)
8369 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8370 continue;
8372 surface_only = TRUE;
8375 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
8377 switch (pools[j].pool)
8379 case D3DPOOL_SYSTEMMEM:
8380 case D3DPOOL_MANAGED:
8381 if (surface_only)
8382 continue;
8383 /* Fall through */
8384 case D3DPOOL_DEFAULT:
8385 if (surface_only)
8387 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8388 formats[i].fmt, pools[j].pool, &surface, NULL);
8389 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8391 else
8393 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8394 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8395 formats[i].fmt, pools[j].pool, &texture, NULL);
8396 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8397 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8398 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8399 IDirect3DTexture9_Release(texture);
8401 break;
8403 case D3DPOOL_SCRATCH:
8404 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8405 formats[i].fmt, pools[j].pool, &surface, NULL);
8406 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8407 break;
8409 default:
8410 break;
8413 if (formats[i].block_width > 1)
8415 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8416 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8417 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8418 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8419 SUCCEEDED(hr) ? "succeeded" : "failed",
8420 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8421 if (SUCCEEDED(hr))
8423 hr = IDirect3DSurface9_UnlockRect(surface);
8424 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8427 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8428 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8429 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8430 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8431 SUCCEEDED(hr) ? "succeeded" : "failed",
8432 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8433 if (SUCCEEDED(hr))
8435 hr = IDirect3DSurface9_UnlockRect(surface);
8436 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8440 if (formats[i].block_height > 1)
8442 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
8443 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8444 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8445 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8446 SUCCEEDED(hr) ? "succeeded" : "failed",
8447 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8448 if (SUCCEEDED(hr))
8450 hr = IDirect3DSurface9_UnlockRect(surface);
8451 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8454 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
8455 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8456 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8457 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8458 SUCCEEDED(hr) ? "succeeded" : "failed",
8459 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8460 if (SUCCEEDED(hr))
8462 hr = IDirect3DSurface9_UnlockRect(surface);
8463 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8467 for (k = 0; k < sizeof(invalid) / sizeof(*invalid); ++k)
8469 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
8470 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
8471 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
8472 formats[i].name, pools[j].name, k);
8473 if (SUCCEEDED(hr))
8475 hr = IDirect3DSurface9_UnlockRect(surface);
8476 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8480 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8481 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8482 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
8483 hr = IDirect3DSurface9_UnlockRect(surface);
8484 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8486 IDirect3DSurface9_Release(surface);
8489 if (!dynamic_tex_support)
8491 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
8492 continue;
8495 if (formats[i].block_width == 1 && formats[i].block_height == 1)
8496 continue;
8497 if (!formats[i].core_fmt)
8498 continue;
8500 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
8501 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
8502 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
8504 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
8505 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8506 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8507 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8509 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
8510 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
8511 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8512 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8513 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8514 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8516 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8517 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8518 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8519 if (SUCCEEDED(hr))
8520 IDirect3DTexture9_UnlockRect(texture, 1);
8522 IDirect3DTexture9_Release(texture);
8525 refcount = IDirect3DDevice9_Release(device);
8526 ok(!refcount, "Device has %u references left.\n", refcount);
8527 IDirect3D9_Release(d3d);
8528 DestroyWindow(window);
8531 static void test_set_palette(void)
8533 IDirect3DDevice9 *device;
8534 IDirect3D9 *d3d9;
8535 UINT refcount;
8536 HWND window;
8537 HRESULT hr;
8538 PALETTEENTRY pal[256];
8539 unsigned int i;
8540 D3DCAPS9 caps;
8542 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8543 0, 0, 640, 480, 0, 0, 0, 0);
8544 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8545 ok(!!d3d9, "Failed to create a D3D object.\n");
8546 if (!(device = create_device(d3d9, window, NULL)))
8548 skip("Failed to create a D3D device, skipping tests.\n");
8549 DestroyWindow(window);
8550 return;
8553 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8555 pal[i].peRed = i;
8556 pal[i].peGreen = i;
8557 pal[i].peBlue = i;
8558 pal[i].peFlags = 0xff;
8560 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8561 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8563 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8564 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8565 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8567 pal[i].peRed = i;
8568 pal[i].peGreen = i;
8569 pal[i].peBlue = i;
8570 pal[i].peFlags = i;
8572 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
8574 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8575 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8577 else
8579 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8580 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
8583 refcount = IDirect3DDevice9_Release(device);
8584 ok(!refcount, "Device has %u references left.\n", refcount);
8585 IDirect3D9_Release(d3d9);
8586 DestroyWindow(window);
8589 static void test_swvp_buffer(void)
8591 IDirect3DDevice9 *device;
8592 IDirect3D9 *d3d9;
8593 UINT refcount;
8594 HWND window;
8595 HRESULT hr;
8596 unsigned int i;
8597 IDirect3DVertexBuffer9 *buffer;
8598 static const unsigned int bufsize = 1024;
8599 D3DVERTEXBUFFER_DESC desc;
8600 struct device_desc device_desc;
8601 struct
8603 float x, y, z;
8604 } *ptr, *ptr2;
8606 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8607 0, 0, 640, 480, 0, 0, 0, 0);
8608 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8609 ok(!!d3d9, "Failed to create a D3D object.\n");
8611 device_desc.device_window = window;
8612 device_desc.width = 640;
8613 device_desc.height = 480;
8614 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
8615 if (!(device = create_device(d3d9, window, &device_desc)))
8617 skip("Failed to create a D3D device, skipping tests.\n");
8618 DestroyWindow(window);
8619 IDirect3D9_Release(d3d9);
8620 return;
8623 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
8624 D3DPOOL_DEFAULT, &buffer, NULL);
8625 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8626 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8627 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8628 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
8629 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
8630 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
8632 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8633 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8634 for (i = 0; i < bufsize; i++)
8636 ptr[i].x = i * 1.0f;
8637 ptr[i].y = i * 2.0f;
8638 ptr[i].z = i * 3.0f;
8640 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8641 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8643 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8644 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8645 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8646 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8647 hr = IDirect3DDevice9_BeginScene(device);
8648 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8649 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8650 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8651 hr = IDirect3DDevice9_EndScene(device);
8652 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8654 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8655 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8656 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
8657 for (i = 0; i < bufsize; i++)
8659 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8661 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
8662 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8663 break;
8666 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8667 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8669 IDirect3DVertexBuffer9_Release(buffer);
8670 refcount = IDirect3DDevice9_Release(device);
8671 ok(!refcount, "Device has %u references left.\n", refcount);
8672 IDirect3D9_Release(d3d9);
8673 DestroyWindow(window);
8676 static void test_managed_buffer(void)
8678 static const unsigned int vertex_count = 1024;
8679 IDirect3DVertexBuffer9 *buffer;
8680 D3DVERTEXBUFFER_DESC desc;
8681 IDirect3DDevice9 *device;
8682 struct vec3 *ptr, *ptr2;
8683 IDirect3D9 *d3d9;
8684 unsigned int i;
8685 UINT refcount;
8686 HWND window;
8687 HRESULT hr;
8689 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8690 0, 0, 640, 480, 0, 0, 0, 0);
8691 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8692 ok(!!d3d9, "Failed to create a D3D object.\n");
8693 if (!(device = create_device(d3d9, window, NULL)))
8695 skip("Failed to create a D3D device, skipping tests.\n");
8696 IDirect3D9_Release(d3d9);
8697 DestroyWindow(window);
8698 return;
8701 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
8702 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
8703 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8704 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8705 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8706 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
8707 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
8709 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8710 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8711 for (i = 0; i < vertex_count; ++i)
8713 ptr[i].x = i * 1.0f;
8714 ptr[i].y = i * 2.0f;
8715 ptr[i].z = i * 3.0f;
8717 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8718 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8720 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8721 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8722 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8723 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8724 hr = IDirect3DDevice9_BeginScene(device);
8725 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8726 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8727 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8728 hr = IDirect3DDevice9_EndScene(device);
8729 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8731 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8732 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8733 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
8734 for (i = 0; i < vertex_count; ++i)
8736 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8738 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
8739 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8740 break;
8743 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8744 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8746 IDirect3DVertexBuffer9_Release(buffer);
8747 refcount = IDirect3DDevice9_Release(device);
8748 ok(!refcount, "Device has %u references left.\n", refcount);
8749 IDirect3D9_Release(d3d9);
8750 DestroyWindow(window);
8753 static void test_npot_textures(void)
8755 IDirect3DDevice9 *device = NULL;
8756 IDirect3D9 *d3d9;
8757 ULONG refcount;
8758 HWND window = NULL;
8759 HRESULT hr;
8760 D3DCAPS9 caps;
8761 IDirect3DTexture9 *texture;
8762 IDirect3DCubeTexture9 *cube_texture;
8763 IDirect3DVolumeTexture9 *volume_texture;
8764 struct
8766 D3DPOOL pool;
8767 const char *pool_name;
8768 HRESULT hr;
8770 pools[] =
8772 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
8773 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
8774 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
8775 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
8777 unsigned int i, levels;
8778 BOOL tex_pow2, cube_pow2, vol_pow2;
8780 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8781 0, 0, 640, 480, 0, 0, 0, 0);
8782 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8783 ok(!!d3d9, "Failed to create a D3D object.\n");
8784 if (!(device = create_device(d3d9, window, NULL)))
8786 skip("Failed to create a D3D device, skipping tests.\n");
8787 goto done;
8790 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8791 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8792 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8793 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8794 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8795 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
8796 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
8798 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
8800 for (levels = 0; levels <= 2; levels++)
8802 HRESULT expected;
8804 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
8805 pools[i].pool, &texture, NULL);
8806 if (!tex_pow2)
8808 expected = D3D_OK;
8810 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
8812 if (levels == 1)
8813 expected = D3D_OK;
8814 else
8815 expected = pools[i].hr;
8817 else
8819 expected = pools[i].hr;
8821 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
8822 pools[i].pool_name, levels, hr, expected);
8824 if (SUCCEEDED(hr))
8825 IDirect3DTexture9_Release(texture);
8828 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8829 &cube_texture, NULL);
8830 if (tex_pow2)
8832 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8833 pools[i].pool_name, hr, pools[i].hr);
8835 else
8837 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8838 pools[i].pool_name, hr, D3D_OK);
8841 if (SUCCEEDED(hr))
8842 IDirect3DCubeTexture9_Release(cube_texture);
8844 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8845 &volume_texture, NULL);
8846 if (tex_pow2)
8848 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8849 pools[i].pool_name, hr, pools[i].hr);
8851 else
8853 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8854 pools[i].pool_name, hr, D3D_OK);
8857 if (SUCCEEDED(hr))
8858 IDirect3DVolumeTexture9_Release(volume_texture);
8861 done:
8862 if (device)
8864 refcount = IDirect3DDevice9_Release(device);
8865 ok(!refcount, "Device has %u references left.\n", refcount);
8867 IDirect3D9_Release(d3d9);
8868 DestroyWindow(window);
8872 static void test_vidmem_accounting(void)
8874 IDirect3DDevice9 *device;
8875 IDirect3D9 *d3d9;
8876 ULONG refcount;
8877 HWND window;
8878 HRESULT hr = D3D_OK;
8879 IDirect3DTexture9 *textures[20];
8880 unsigned int i;
8881 UINT vidmem_start, vidmem_end, diff;
8883 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8884 0, 0, 640, 480, 0, 0, 0, 0);
8885 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8886 ok(!!d3d9, "Failed to create a D3D object.\n");
8887 if (!(device = create_device(d3d9, window, NULL)))
8889 skip("Failed to create a D3D device, skipping tests.\n");
8890 IDirect3D9_Release(d3d9);
8891 DestroyWindow(window);
8892 return;
8895 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
8896 memset(textures, 0, sizeof(textures));
8897 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
8899 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
8900 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
8901 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
8902 * E_FAIL is returned on address space or system memory exhaustion */
8903 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
8904 "Failed to create texture, hr %#x.\n", hr);
8906 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
8908 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
8909 diff = vidmem_start - vidmem_end;
8910 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
8911 2 * i, diff / 1024 / 1024);
8913 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
8915 if (textures[i])
8916 IDirect3DTexture9_Release(textures[i]);
8919 refcount = IDirect3DDevice9_Release(device);
8920 ok(!refcount, "Device has %u references left.\n", refcount);
8921 IDirect3D9_Release(d3d9);
8922 DestroyWindow(window);
8925 static void test_volume_locking(void)
8927 IDirect3DDevice9 *device;
8928 IDirect3D9 *d3d9;
8929 HWND window;
8930 HRESULT hr;
8931 IDirect3DVolumeTexture9 *texture;
8932 unsigned int i;
8933 D3DLOCKED_BOX locked_box;
8934 ULONG refcount;
8935 D3DCAPS9 caps;
8936 static const struct
8938 D3DPOOL pool;
8939 DWORD usage;
8940 HRESULT create_hr, lock_hr;
8942 tests[] =
8944 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
8945 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
8946 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
8947 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
8948 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
8949 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
8950 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
8951 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
8954 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8955 0, 0, 640, 480, 0, 0, 0, 0);
8956 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8957 ok(!!d3d9, "Failed to create a D3D object.\n");
8958 if (!(device = create_device(d3d9, window, NULL)))
8960 skip("Failed to create a D3D device, skipping tests.\n");
8961 IDirect3D9_Release(d3d9);
8962 DestroyWindow(window);
8963 return;
8966 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8967 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8968 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
8970 skip("Volume textures not supported, skipping test.\n");
8971 goto out;
8974 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8976 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
8977 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
8978 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
8979 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
8980 if (FAILED(hr))
8981 continue;
8983 locked_box.pBits = (void *)0xdeadbeef;
8984 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
8985 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
8986 if (SUCCEEDED(hr))
8988 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8989 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8991 else
8993 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
8995 IDirect3DVolumeTexture9_Release(texture);
8998 out:
8999 refcount = IDirect3DDevice9_Release(device);
9000 ok(!refcount, "Device has %u references left.\n", refcount);
9001 IDirect3D9_Release(d3d9);
9002 DestroyWindow(window);
9005 static void test_update_volumetexture(void)
9007 IDirect3DDevice9 *device;
9008 IDirect3D9 *d3d9;
9009 HWND window;
9010 HRESULT hr;
9011 IDirect3DVolumeTexture9 *src, *dst;
9012 unsigned int i;
9013 D3DLOCKED_BOX locked_box;
9014 ULONG refcount;
9015 D3DCAPS9 caps;
9016 static const struct
9018 D3DPOOL src_pool, dst_pool;
9019 HRESULT hr;
9021 tests[] =
9023 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9024 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9025 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9026 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9028 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9029 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9030 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9031 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9033 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9034 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9035 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9036 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9038 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9039 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9040 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9041 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9043 static const struct
9045 UINT src_size, dst_size;
9046 UINT src_lvl, dst_lvl;
9047 D3DFORMAT src_fmt, dst_fmt;
9049 tests2[] =
9051 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9052 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9053 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9054 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9055 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9056 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9057 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9058 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9061 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9062 0, 0, 640, 480, 0, 0, 0, 0);
9063 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9064 ok(!!d3d9, "Failed to create a D3D object.\n");
9065 if (!(device = create_device(d3d9, window, NULL)))
9067 skip("Failed to create a D3D device, skipping tests.\n");
9068 IDirect3D9_Release(d3d9);
9069 DestroyWindow(window);
9070 return;
9073 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9074 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9075 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9077 skip("Volume textures not supported, skipping test.\n");
9078 goto out;
9081 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9083 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9084 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9086 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9087 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9088 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9089 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9090 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9091 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9093 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9094 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9095 *((DWORD *)locked_box.pBits) = 0x11223344;
9096 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9097 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9099 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9100 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9101 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9103 if (SUCCEEDED(hr))
9105 DWORD content = *((DWORD *)locked_box.pBits);
9106 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9107 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9108 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9109 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9110 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9112 IDirect3DVolumeTexture9_Release(src);
9113 IDirect3DVolumeTexture9_Release(dst);
9116 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9118 skip("Mipmapped volume maps not supported.\n");
9119 goto out;
9122 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
9124 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9125 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9126 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9127 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9128 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9129 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9130 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9131 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9133 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9134 todo_wine_if (FAILED(hr))
9135 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9137 IDirect3DVolumeTexture9_Release(src);
9138 IDirect3DVolumeTexture9_Release(dst);
9141 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9142 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9143 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9144 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9145 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9147 * I'm not adding tests for this behavior until an application needs it. */
9149 out:
9150 refcount = IDirect3DDevice9_Release(device);
9151 ok(!refcount, "Device has %u references left.\n", refcount);
9152 IDirect3D9_Release(d3d9);
9153 DestroyWindow(window);
9156 static void test_create_rt_ds_fail(void)
9158 IDirect3DDevice9 *device;
9159 HWND window;
9160 HRESULT hr;
9161 ULONG refcount;
9162 IDirect3D9 *d3d9;
9163 IDirect3DSurface9 *surface;
9165 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9166 0, 0, 640, 480, 0, 0, 0, 0);
9167 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9168 ok(!!d3d9, "Failed to create a D3D object.\n");
9169 if (!(device = create_device(d3d9, window, NULL)))
9171 skip("Failed to create a D3D device, skipping tests.\n");
9172 IDirect3D9_Release(d3d9);
9173 DestroyWindow(window);
9174 return;
9177 /* Output pointer == NULL segfaults on Windows. */
9179 surface = (IDirect3DSurface9 *)0xdeadbeef;
9180 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9181 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9182 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9183 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9184 if (SUCCEEDED(hr))
9185 IDirect3DSurface9_Release(surface);
9187 surface = (IDirect3DSurface9 *)0xdeadbeef;
9188 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9189 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9190 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9191 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9192 if (SUCCEEDED(hr))
9193 IDirect3DSurface9_Release(surface);
9195 refcount = IDirect3DDevice9_Release(device);
9196 ok(!refcount, "Device has %u references left.\n", refcount);
9197 IDirect3D9_Release(d3d9);
9198 DestroyWindow(window);
9201 static void test_volume_blocks(void)
9203 IDirect3DDevice9 *device;
9204 IDirect3D9 *d3d9;
9205 UINT refcount;
9206 HWND window;
9207 HRESULT hr;
9208 D3DCAPS9 caps;
9209 IDirect3DVolumeTexture9 *texture;
9210 unsigned int w, h, d, i, j;
9211 static const struct
9213 D3DFORMAT fmt;
9214 const char *name;
9215 unsigned int block_width;
9216 unsigned int block_height;
9217 unsigned int block_depth;
9218 unsigned int block_size;
9219 unsigned int broken;
9220 BOOL create_size_checked, core_fmt;
9222 formats[] =
9224 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9225 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9226 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9227 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9228 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9229 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9230 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9231 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9232 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9233 * which doesn't match the format spec. On newer Nvidia cards
9234 * it has the correct 4x4 block size.
9235 * ATI1N volume textures are only supported by AMD GPUs right
9236 * now and locking offsets seem just wrong. */
9237 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9238 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9239 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9240 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9242 static const struct
9244 D3DPOOL pool;
9245 const char *name;
9246 BOOL need_driver_support, need_runtime_support;
9248 create_tests[] =
9250 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9251 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9252 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9253 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9255 static const struct
9257 unsigned int x, y, z, x2, y2, z2;
9259 offset_tests[] =
9261 {0, 0, 0, 8, 8, 8},
9262 {0, 0, 3, 8, 8, 8},
9263 {0, 4, 0, 8, 8, 8},
9264 {0, 4, 3, 8, 8, 8},
9265 {4, 0, 0, 8, 8, 8},
9266 {4, 0, 3, 8, 8, 8},
9267 {4, 4, 0, 8, 8, 8},
9268 {4, 4, 3, 8, 8, 8},
9270 D3DBOX box;
9271 D3DLOCKED_BOX locked_box;
9272 BYTE *base;
9273 INT expected_row_pitch, expected_slice_pitch;
9274 BOOL support;
9275 BOOL pow2;
9276 unsigned int offset, expected_offset;
9278 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9279 0, 0, 640, 480, 0, 0, 0, 0);
9280 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9281 ok(!!d3d9, "Failed to create a D3D object.\n");
9282 if (!(device = create_device(d3d9, window, NULL)))
9284 skip("Failed to create a D3D device, skipping tests.\n");
9285 IDirect3D9_Release(d3d9);
9286 DestroyWindow(window);
9287 return;
9289 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9290 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9291 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9293 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
9295 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9296 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9297 support = SUCCEEDED(hr);
9299 /* Test creation restrictions */
9300 for (w = 1; w <= 8; w++)
9302 for (h = 1; h <= 8; h++)
9304 for (d = 1; d <= 8; d++)
9306 HRESULT expect_hr;
9307 BOOL size_is_pow2;
9308 BOOL block_aligned = TRUE;
9310 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9311 block_aligned = FALSE;
9313 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9315 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
9317 BOOL may_succeed = FALSE;
9319 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9320 expect_hr = D3DERR_INVALIDCALL;
9321 else if (formats[i].create_size_checked && !block_aligned)
9322 expect_hr = D3DERR_INVALIDCALL;
9323 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9324 expect_hr = D3DERR_INVALIDCALL;
9325 else if (create_tests[j].need_driver_support && !support)
9326 expect_hr = D3DERR_INVALIDCALL;
9327 else
9328 expect_hr = D3D_OK;
9330 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9331 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9332 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9334 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9335 * does not support it. Accept scratch creation of extension formats on
9336 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9337 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9338 * support it. */
9339 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9340 may_succeed = TRUE;
9342 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9343 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9344 hr, formats[i].name, create_tests[j].name, w, h, d);
9346 if (FAILED(hr))
9347 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9348 else
9349 IDirect3DVolumeTexture9_Release(texture);
9355 if (!support && !formats[i].core_fmt)
9356 continue;
9358 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9359 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9360 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9362 /* Test lockrect offset */
9363 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
9365 unsigned int bytes_per_pixel;
9366 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9368 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9369 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9371 base = locked_box.pBits;
9372 if (formats[i].broken == 1)
9374 expected_row_pitch = bytes_per_pixel * 24;
9376 else if (formats[i].broken == 2)
9378 expected_row_pitch = 24;
9380 else
9382 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9383 * formats[i].block_size;
9385 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9386 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9388 if (formats[i].broken)
9390 expected_slice_pitch = expected_row_pitch * 8;
9392 else
9394 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9395 * expected_row_pitch;
9397 ok(locked_box.SlicePitch == expected_slice_pitch,
9398 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9399 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9401 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9402 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9404 box.Left = offset_tests[j].x;
9405 box.Top = offset_tests[j].y;
9406 box.Front = offset_tests[j].z;
9407 box.Right = offset_tests[j].x2;
9408 box.Bottom = offset_tests[j].y2;
9409 box.Back = offset_tests[j].z2;
9410 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9411 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9413 offset = (BYTE *)locked_box.pBits - base;
9414 if (formats[i].broken == 1)
9416 expected_offset = box.Front * expected_slice_pitch
9417 + box.Top * expected_row_pitch
9418 + box.Left * bytes_per_pixel;
9420 else if (formats[i].broken == 2)
9422 expected_offset = box.Front * expected_slice_pitch
9423 + box.Top * expected_row_pitch
9424 + box.Left;
9426 else
9428 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9429 + (box.Top / formats[i].block_height) * expected_row_pitch
9430 + (box.Left / formats[i].block_width) * formats[i].block_size;
9432 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9433 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9435 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9436 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9439 /* Test partial block locks */
9440 box.Front = 0;
9441 box.Back = 1;
9442 if (formats[i].block_width > 1)
9444 box.Left = formats[i].block_width >> 1;
9445 box.Top = 0;
9446 box.Right = formats[i].block_width;
9447 box.Bottom = formats[i].block_height;
9448 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9449 ok(FAILED(hr) || broken(formats[i].broken),
9450 "Partial block lock succeeded, expected failure, format %s.\n",
9451 formats[i].name);
9452 if (SUCCEEDED(hr))
9454 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9455 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9458 box.Left = 0;
9459 box.Top = 0;
9460 box.Right = formats[i].block_width >> 1;
9461 box.Bottom = formats[i].block_height;
9462 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9463 ok(FAILED(hr) || broken(formats[i].broken),
9464 "Partial block lock succeeded, expected failure, format %s.\n",
9465 formats[i].name);
9466 if (SUCCEEDED(hr))
9468 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9469 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9473 if (formats[i].block_height > 1)
9475 box.Left = 0;
9476 box.Top = formats[i].block_height >> 1;
9477 box.Right = formats[i].block_width;
9478 box.Bottom = formats[i].block_height;
9479 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9480 ok(FAILED(hr) || broken(formats[i].broken),
9481 "Partial block lock succeeded, expected failure, format %s.\n",
9482 formats[i].name);
9483 if (SUCCEEDED(hr))
9485 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9486 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9489 box.Left = 0;
9490 box.Top = 0;
9491 box.Right = formats[i].block_width;
9492 box.Bottom = formats[i].block_height >> 1;
9493 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9494 ok(FAILED(hr) || broken(formats[i].broken),
9495 "Partial block lock succeeded, expected failure, format %s.\n",
9496 formats[i].name);
9497 if (SUCCEEDED(hr))
9499 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9500 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9504 /* Test full block lock */
9505 box.Left = 0;
9506 box.Top = 0;
9507 box.Right = formats[i].block_width;
9508 box.Bottom = formats[i].block_height;
9509 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9510 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9511 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9512 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9514 IDirect3DVolumeTexture9_Release(texture);
9516 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
9517 * does not allocate surfaces smaller than the blocksize properly. */
9518 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
9520 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
9521 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9522 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9524 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
9525 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9526 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9527 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9529 box.Left = box.Top = box.Front = 0;
9530 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
9531 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
9532 box.Back = 1;
9533 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9534 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9535 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9536 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9538 box.Right = formats[i].block_width;
9539 box.Bottom = formats[i].block_height;
9540 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9541 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9542 if (SUCCEEDED(hr))
9543 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9545 IDirect3DVolumeTexture9_Release(texture);
9549 refcount = IDirect3DDevice9_Release(device);
9550 ok(!refcount, "Device has %u references left.\n", refcount);
9551 IDirect3D9_Release(d3d9);
9552 DestroyWindow(window);
9555 static void test_lockbox_invalid(void)
9557 static const struct
9559 D3DBOX box;
9560 HRESULT result;
9562 test_data[] =
9564 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
9565 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
9566 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
9567 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
9568 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
9569 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
9570 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
9571 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
9572 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
9573 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
9574 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
9575 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
9576 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
9577 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
9579 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
9580 IDirect3DVolumeTexture9 *texture = NULL;
9581 D3DLOCKED_BOX locked_box;
9582 IDirect3DDevice9 *device;
9583 IDirect3D9 *d3d;
9584 unsigned int i;
9585 ULONG refcount;
9586 HWND window;
9587 BYTE *base;
9588 HRESULT hr;
9590 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9591 0, 0, 640, 480, 0, 0, 0, 0);
9592 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9593 ok(!!d3d, "Failed to create a D3D object.\n");
9594 if (!(device = create_device(d3d, window, NULL)))
9596 skip("Failed to create a D3D device, skipping tests.\n");
9597 IDirect3D9_Release(d3d);
9598 DestroyWindow(window);
9599 return;
9602 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
9603 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
9604 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9605 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9606 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9607 base = locked_box.pBits;
9608 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9609 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9611 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
9613 unsigned int offset, expected_offset;
9614 const D3DBOX *box = &test_data[i].box;
9616 locked_box.pBits = (BYTE *)0xdeadbeef;
9617 locked_box.RowPitch = 0xdeadbeef;
9618 locked_box.SlicePitch = 0xdeadbeef;
9620 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
9621 /* Unlike surfaces, volumes properly check the box even in Windows XP */
9622 ok(hr == test_data[i].result,
9623 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
9624 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
9625 test_data[i].result);
9626 if (FAILED(hr))
9627 continue;
9629 offset = (BYTE *)locked_box.pBits - base;
9630 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
9631 ok(offset == expected_offset,
9632 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
9633 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
9635 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9636 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9639 /* locked_box = NULL throws an exception on Windows */
9640 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9641 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9642 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9643 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9644 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9645 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9646 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9647 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9649 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9650 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9651 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9652 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9653 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9654 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9655 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9656 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9657 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
9658 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9659 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
9660 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
9661 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9662 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9664 IDirect3DVolumeTexture9_Release(texture);
9665 refcount = IDirect3DDevice9_Release(device);
9666 ok(!refcount, "Device has %u references left.\n", refcount);
9667 IDirect3D9_Release(d3d);
9668 DestroyWindow(window);
9671 static void test_shared_handle(void)
9673 IDirect3DDevice9 *device;
9674 IDirect3D9 *d3d;
9675 ULONG refcount;
9676 HWND window;
9677 HRESULT hr;
9678 /* Native d3d9ex refuses to create a shared texture if the texture pointer
9679 * is not initialized to NULL. Make sure this doesn't cause issues here. */
9680 IDirect3DTexture9 *texture = NULL;
9681 IDirect3DSurface9 *surface = NULL;
9682 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
9683 IDirect3DIndexBuffer9 *index_buffer = NULL;
9684 HANDLE handle = NULL;
9685 void *mem;
9686 D3DCAPS9 caps;
9688 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9689 0, 0, 640, 480, 0, 0, 0, 0);
9690 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9691 ok(!!d3d, "Failed to create a D3D object.\n");
9692 if (!(device = create_device(d3d, window, NULL)))
9694 skip("Failed to create a D3D device, skipping tests.\n");
9695 IDirect3D9_Release(d3d);
9696 DestroyWindow(window);
9697 return;
9700 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9701 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9702 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
9704 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
9705 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
9706 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9707 D3DPOOL_DEFAULT, &texture, &handle);
9708 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9709 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9710 D3DPOOL_SYSTEMMEM, &texture, &mem);
9711 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9713 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9714 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
9715 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9716 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9717 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
9718 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9720 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9721 &vertex_buffer, &handle);
9722 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9723 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9724 &vertex_buffer, &mem);
9725 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
9727 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9728 &index_buffer, &handle);
9729 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9730 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9731 &index_buffer, &mem);
9732 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9734 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9736 IDirect3DCubeTexture9 *cube_texture = NULL;
9737 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9738 D3DPOOL_DEFAULT, &cube_texture, &handle);
9739 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9740 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9741 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
9742 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9745 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
9747 IDirect3DVolumeTexture9 *volume_texture = NULL;
9748 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9749 D3DPOOL_DEFAULT, &volume_texture, &handle);
9750 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9751 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9752 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
9753 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9756 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
9757 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9758 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9760 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
9761 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9762 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9764 HeapFree(GetProcessHeap(), 0, mem);
9765 refcount = IDirect3DDevice9_Release(device);
9766 ok(!refcount, "Device has %u references left.\n", refcount);
9767 IDirect3D9_Release(d3d);
9768 DestroyWindow(window);
9771 static void test_pixel_format(void)
9773 HWND hwnd, hwnd2 = NULL;
9774 HDC hdc, hdc2 = NULL;
9775 HMODULE gl = NULL;
9776 int format, test_format;
9777 PIXELFORMATDESCRIPTOR pfd;
9778 IDirect3D9 *d3d9 = NULL;
9779 IDirect3DDevice9 *device = NULL;
9780 HRESULT hr;
9781 static const float point[3] = {0.0, 0.0, 0.0};
9783 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9784 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9785 if (!hwnd)
9787 skip("Failed to create window\n");
9788 return;
9791 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9792 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9794 hdc = GetDC(hwnd);
9795 if (!hdc)
9797 skip("Failed to get DC\n");
9798 goto cleanup;
9801 if (hwnd2)
9802 hdc2 = GetDC(hwnd2);
9804 gl = LoadLibraryA("opengl32.dll");
9805 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
9807 format = GetPixelFormat(hdc);
9808 ok(format == 0, "new window has pixel format %d\n", format);
9810 ZeroMemory(&pfd, sizeof(pfd));
9811 pfd.nSize = sizeof(pfd);
9812 pfd.nVersion = 1;
9813 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
9814 pfd.iPixelType = PFD_TYPE_RGBA;
9815 pfd.iLayerType = PFD_MAIN_PLANE;
9816 format = ChoosePixelFormat(hdc, &pfd);
9817 if (format <= 0)
9819 skip("no pixel format available\n");
9820 goto cleanup;
9823 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
9825 skip("failed to set pixel format\n");
9826 goto cleanup;
9829 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
9831 skip("failed to set pixel format on second window\n");
9832 if (hdc2)
9834 ReleaseDC(hwnd2, hdc2);
9835 hdc2 = NULL;
9839 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9840 ok(!!d3d9, "Failed to create a D3D object.\n");
9842 test_format = GetPixelFormat(hdc);
9843 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9845 if (!(device = create_device(d3d9, hwnd, NULL)))
9847 skip("Failed to create device\n");
9848 goto cleanup;
9851 test_format = GetPixelFormat(hdc);
9852 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9854 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9855 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
9857 test_format = GetPixelFormat(hdc);
9858 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9860 hr = IDirect3DDevice9_BeginScene(device);
9861 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
9863 test_format = GetPixelFormat(hdc);
9864 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9866 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
9867 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9869 test_format = GetPixelFormat(hdc);
9870 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9872 hr = IDirect3DDevice9_EndScene(device);
9873 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
9875 test_format = GetPixelFormat(hdc);
9876 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9878 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9879 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9881 test_format = GetPixelFormat(hdc);
9882 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9884 if (hdc2)
9886 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
9887 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9889 test_format = GetPixelFormat(hdc);
9890 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9892 test_format = GetPixelFormat(hdc2);
9893 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
9896 cleanup:
9897 if (device)
9899 UINT refcount = IDirect3DDevice9_Release(device);
9900 ok(!refcount, "Device has %u references left.\n", refcount);
9902 if (d3d9) IDirect3D9_Release(d3d9);
9903 if (gl) FreeLibrary(gl);
9904 if (hdc) ReleaseDC(hwnd, hdc);
9905 if (hdc2) ReleaseDC(hwnd2, hdc2);
9906 if (hwnd) DestroyWindow(hwnd);
9907 if (hwnd2) DestroyWindow(hwnd2);
9910 static void test_begin_end_state_block(void)
9912 IDirect3DStateBlock9 *stateblock;
9913 IDirect3DDevice9 *device;
9914 IDirect3D9 *d3d;
9915 ULONG refcount;
9916 HWND window;
9917 HRESULT hr;
9919 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9920 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9921 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9922 ok(!!d3d, "Failed to create a D3D object.\n");
9923 if (!(device = create_device(d3d, window, NULL)))
9925 skip("Failed to create a D3D device, skipping tests.\n");
9926 IDirect3D9_Release(d3d);
9927 DestroyWindow(window);
9928 return;
9931 /* Should succeed. */
9932 hr = IDirect3DDevice9_BeginStateBlock(device);
9933 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
9935 /* Calling BeginStateBlock() while recording should return
9936 * D3DERR_INVALIDCALL. */
9937 hr = IDirect3DDevice9_BeginStateBlock(device);
9938 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9940 /* Should succeed. */
9941 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
9942 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9943 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
9944 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
9945 "Got unexpected stateblock %p.\n", stateblock);
9946 IDirect3DStateBlock9_Release(stateblock);
9948 /* Calling EndStateBlock() while not recording should return
9949 * D3DERR_INVALIDCALL. stateblock should not be touched. */
9950 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
9951 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9952 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9953 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
9954 "Got unexpected stateblock %p.\n", stateblock);
9956 refcount = IDirect3DDevice9_Release(device);
9957 ok(!refcount, "Device has %u references left.\n", refcount);
9958 IDirect3D9_Release(d3d);
9959 DestroyWindow(window);
9962 static void test_shader_constant_apply(void)
9964 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
9965 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
9966 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
9967 IDirect3DStateBlock9 *stateblock;
9968 DWORD vs_version, ps_version;
9969 IDirect3DDevice9 *device;
9970 IDirect3D9 *d3d;
9971 ULONG refcount;
9972 D3DCAPS9 caps;
9973 float ret[4];
9974 HWND window;
9975 HRESULT hr;
9977 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9978 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9979 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9980 ok(!!d3d, "Failed to create a D3D object.\n");
9981 if (!(device = create_device(d3d, window, NULL)))
9983 skip("Failed to create a D3D device, skipping tests.\n");
9984 IDirect3D9_Release(d3d);
9985 DestroyWindow(window);
9986 return;
9989 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9990 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9991 vs_version = caps.VertexShaderVersion & 0xffff;
9992 ps_version = caps.PixelShaderVersion & 0xffff;
9994 if (vs_version)
9996 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
9997 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9998 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
9999 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10001 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10002 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10003 ok(!memcmp(ret, initial, sizeof(initial)),
10004 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10005 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10006 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10007 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10008 ok(!memcmp(ret, initial, sizeof(initial)),
10009 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10010 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10012 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10013 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10015 if (ps_version)
10017 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10018 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10019 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10020 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10022 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10023 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10024 ok(!memcmp(ret, initial, sizeof(initial)),
10025 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10026 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10027 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10028 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10029 ok(!memcmp(ret, initial, sizeof(initial)),
10030 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10031 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10033 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10034 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10037 hr = IDirect3DDevice9_BeginStateBlock(device);
10038 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10040 if (vs_version)
10042 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10043 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10045 if (ps_version)
10047 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10048 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10051 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10052 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10054 if (vs_version)
10056 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10057 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10058 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10059 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10060 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10061 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10062 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10063 ok(!memcmp(ret, initial, sizeof(initial)),
10064 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10065 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10067 if (ps_version)
10069 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10070 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10071 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10072 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10073 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10074 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10075 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10076 ok(!memcmp(ret, initial, sizeof(initial)),
10077 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10078 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10081 /* Apply doesn't overwrite constants that aren't explicitly set on the
10082 * source stateblock. */
10083 hr = IDirect3DStateBlock9_Apply(stateblock);
10084 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10086 if (vs_version)
10088 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10089 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10090 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10091 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10092 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10093 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10094 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10095 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10096 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10097 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10099 if (ps_version)
10101 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10102 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10103 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10104 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10105 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10106 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10107 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10108 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10109 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10110 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10113 IDirect3DStateBlock9_Release(stateblock);
10114 refcount = IDirect3DDevice9_Release(device);
10115 ok(!refcount, "Device has %u references left.\n", refcount);
10116 IDirect3D9_Release(d3d);
10117 DestroyWindow(window);
10120 static void test_vdecl_apply(void)
10122 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10123 IDirect3DStateBlock9 *stateblock;
10124 IDirect3DDevice9 *device;
10125 IDirect3D9 *d3d;
10126 ULONG refcount;
10127 HWND window;
10128 HRESULT hr;
10130 static const D3DVERTEXELEMENT9 decl1[] =
10132 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10133 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10134 D3DDECL_END(),
10137 static const D3DVERTEXELEMENT9 decl2[] =
10139 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10140 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10141 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10142 D3DDECL_END(),
10145 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10146 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10147 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10148 ok(!!d3d, "Failed to create a D3D object.\n");
10149 if (!(device = create_device(d3d, window, NULL)))
10151 skip("Failed to create a D3D device, skipping tests.\n");
10152 IDirect3D9_Release(d3d);
10153 DestroyWindow(window);
10154 return;
10157 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10158 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10160 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10161 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10163 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10164 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10165 hr = IDirect3DDevice9_BeginStateBlock(device);
10166 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10167 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10168 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10169 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10170 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10171 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10172 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10173 hr = IDirect3DStateBlock9_Apply(stateblock);
10174 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10175 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10176 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10177 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10178 declaration, declaration1);
10179 IDirect3DVertexDeclaration9_Release(declaration);
10181 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10182 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10183 hr = IDirect3DStateBlock9_Capture(stateblock);
10184 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10185 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10186 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10187 hr = IDirect3DStateBlock9_Apply(stateblock);
10188 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10189 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10190 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10191 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10192 declaration, declaration2);
10193 IDirect3DVertexDeclaration9_Release(declaration);
10195 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10196 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10197 hr = IDirect3DStateBlock9_Capture(stateblock);
10198 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10199 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10200 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10201 hr = IDirect3DStateBlock9_Apply(stateblock);
10202 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10203 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10204 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10205 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10206 declaration, declaration2);
10207 IDirect3DVertexDeclaration9_Release(declaration);
10209 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10210 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10211 hr = IDirect3DStateBlock9_Capture(stateblock);
10212 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10213 hr = IDirect3DStateBlock9_Apply(stateblock);
10214 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10215 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10216 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10217 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10219 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10220 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10221 hr = IDirect3DStateBlock9_Capture(stateblock);
10222 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10223 hr = IDirect3DStateBlock9_Apply(stateblock);
10224 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10225 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10226 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10227 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10228 declaration, declaration2);
10229 IDirect3DVertexDeclaration9_Release(declaration);
10231 IDirect3DStateBlock9_Release(stateblock);
10232 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10233 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10234 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10235 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10236 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10237 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10238 hr = IDirect3DStateBlock9_Apply(stateblock);
10239 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10240 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10241 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10242 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10243 declaration, declaration1);
10244 IDirect3DVertexDeclaration9_Release(declaration);
10246 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10247 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10248 hr = IDirect3DStateBlock9_Capture(stateblock);
10249 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10250 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10251 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10252 hr = IDirect3DStateBlock9_Apply(stateblock);
10253 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10254 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10255 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10256 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10257 declaration, declaration2);
10258 IDirect3DVertexDeclaration9_Release(declaration);
10260 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10261 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10262 hr = IDirect3DStateBlock9_Capture(stateblock);
10263 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10264 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10265 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10266 hr = IDirect3DStateBlock9_Apply(stateblock);
10267 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10268 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10269 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10270 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10271 declaration, declaration2);
10272 IDirect3DVertexDeclaration9_Release(declaration);
10274 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10275 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10276 hr = IDirect3DStateBlock9_Capture(stateblock);
10277 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10278 hr = IDirect3DStateBlock9_Apply(stateblock);
10279 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10280 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10281 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10282 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10284 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10285 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10286 hr = IDirect3DStateBlock9_Capture(stateblock);
10287 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10288 hr = IDirect3DStateBlock9_Apply(stateblock);
10289 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10290 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10291 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10292 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10293 declaration, declaration2);
10294 IDirect3DVertexDeclaration9_Release(declaration);
10296 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10297 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10298 IDirect3DVertexDeclaration9_Release(declaration1);
10299 IDirect3DVertexDeclaration9_Release(declaration2);
10300 IDirect3DStateBlock9_Release(stateblock);
10301 refcount = IDirect3DDevice9_Release(device);
10302 ok(!refcount, "Device has %u references left.\n", refcount);
10303 IDirect3D9_Release(d3d);
10304 DestroyWindow(window);
10307 static void test_resource_type(void)
10309 IDirect3DDevice9 *device;
10310 IDirect3DSurface9 *surface;
10311 IDirect3DTexture9 *texture;
10312 IDirect3DCubeTexture9 *cube_texture;
10313 IDirect3DVolume9 *volume;
10314 IDirect3DVolumeTexture9 *volume_texture;
10315 D3DSURFACE_DESC surface_desc;
10316 D3DVOLUME_DESC volume_desc;
10317 D3DRESOURCETYPE type;
10318 IDirect3D9 *d3d;
10319 ULONG refcount;
10320 HWND window;
10321 HRESULT hr;
10322 D3DCAPS9 caps;
10324 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10325 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10326 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10327 ok(!!d3d, "Failed to create a D3D object.\n");
10328 if (!(device = create_device(d3d, window, NULL)))
10330 skip("Failed to create a D3D device, skipping tests.\n");
10331 IDirect3D9_Release(d3d);
10332 DestroyWindow(window);
10333 return;
10336 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10337 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10339 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10340 D3DPOOL_SYSTEMMEM, &surface, NULL);
10341 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10342 type = IDirect3DSurface9_GetType(surface);
10343 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10344 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10345 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10346 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10347 surface_desc.Type);
10348 IDirect3DSurface9_Release(surface);
10350 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10351 D3DPOOL_SYSTEMMEM, &texture, NULL);
10352 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10353 type = IDirect3DTexture9_GetType(texture);
10354 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10356 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10357 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10358 /* The following code crashes, for the sake of completeness:
10359 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10360 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10362 * So applications will not depend on getting the "right" resource type - whatever it
10363 * may be - from the "wrong" vtable. */
10364 type = IDirect3DSurface9_GetType(surface);
10365 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10366 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10367 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10368 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10369 surface_desc.Type);
10370 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10371 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10372 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10373 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10374 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10375 surface_desc.Type);
10376 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10377 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10378 IDirect3DSurface9_Release(surface);
10380 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10381 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10382 type = IDirect3DSurface9_GetType(surface);
10383 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10384 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10385 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10386 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10387 surface_desc.Type);
10388 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10389 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10390 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10391 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10392 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10393 surface_desc.Type);
10394 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10395 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10396 IDirect3DSurface9_Release(surface);
10397 IDirect3DTexture9_Release(texture);
10399 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10401 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10402 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10403 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10404 type = IDirect3DCubeTexture9_GetType(cube_texture);
10405 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10407 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10408 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10409 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10410 type = IDirect3DSurface9_GetType(surface);
10411 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10412 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10413 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10414 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10415 surface_desc.Type);
10416 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10417 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10418 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10419 surface_desc.Type);
10420 IDirect3DSurface9_Release(surface);
10421 IDirect3DCubeTexture9_Release(cube_texture);
10423 else
10424 skip("Cube maps not supported.\n");
10426 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10428 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10429 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10430 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10431 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10432 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10434 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10435 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10436 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10437 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10438 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10439 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10440 volume_desc.Type);
10441 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10442 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10443 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10444 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
10445 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10446 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10447 volume_desc.Type);
10448 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10449 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10450 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10451 IDirect3DVolume9_Release(volume);
10453 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
10454 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10455 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10456 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10457 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10458 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10459 volume_desc.Type);
10460 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10461 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10462 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10463 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
10464 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10465 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10466 volume_desc.Type);
10467 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10468 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10469 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10470 IDirect3DVolume9_Release(volume);
10471 IDirect3DVolumeTexture9_Release(volume_texture);
10473 else
10474 skip("Mipmapped volume maps not supported.\n");
10476 refcount = IDirect3DDevice9_Release(device);
10477 ok(!refcount, "Device has %u references left.\n", refcount);
10478 IDirect3D9_Release(d3d);
10479 DestroyWindow(window);
10482 static void test_mipmap_lock(void)
10484 IDirect3DDevice9 *device;
10485 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
10486 IDirect3DTexture9 *texture, *texture_dst;
10487 IDirect3D9 *d3d;
10488 ULONG refcount;
10489 HWND window;
10490 HRESULT hr;
10491 D3DLOCKED_RECT locked_rect;
10493 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10494 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10495 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10496 ok(!!d3d, "Failed to create a D3D object.\n");
10497 if (!(device = create_device(d3d, window, NULL)))
10499 skip("Failed to create a D3D device, skipping tests.\n");
10500 IDirect3D9_Release(d3d);
10501 DestroyWindow(window);
10502 return;
10505 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10506 D3DPOOL_DEFAULT, &texture_dst, NULL);
10507 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10508 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
10509 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10510 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
10511 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10513 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10514 D3DPOOL_SYSTEMMEM, &texture, NULL);
10515 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10516 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10517 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10518 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
10519 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10521 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
10522 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10523 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
10524 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10525 hr = IDirect3DSurface9_UnlockRect(surface);
10526 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10528 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
10529 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
10530 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
10531 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10533 /* Apparently there's no validation on the container. */
10534 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
10535 (IDirect3DBaseTexture9 *)texture_dst);
10536 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
10538 hr = IDirect3DSurface9_UnlockRect(surface2);
10539 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10541 IDirect3DSurface9_Release(surface_dst2);
10542 IDirect3DSurface9_Release(surface_dst);
10543 IDirect3DSurface9_Release(surface2);
10544 IDirect3DSurface9_Release(surface);
10545 IDirect3DTexture9_Release(texture_dst);
10546 IDirect3DTexture9_Release(texture);
10548 refcount = IDirect3DDevice9_Release(device);
10549 ok(!refcount, "Device has %u references left.\n", refcount);
10550 IDirect3D9_Release(d3d);
10551 DestroyWindow(window);
10554 static void test_writeonly_resource(void)
10556 IDirect3D9 *d3d;
10557 IDirect3DDevice9 *device;
10558 IDirect3DVertexBuffer9 *buffer;
10559 ULONG refcount;
10560 HWND window;
10561 HRESULT hr;
10562 void *ptr;
10563 static const struct
10565 struct vec3 pos;
10567 quad[] =
10569 {{-1.0f, -1.0f, 0.0f}},
10570 {{-1.0f, 1.0f, 0.0f}},
10571 {{ 1.0f, -1.0f, 0.0f}},
10572 {{ 1.0f, 1.0f, 0.0f}}
10575 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10576 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10577 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10578 ok(!!d3d, "Failed to create a D3D object.\n");
10579 if (!(device = create_device(d3d, window, NULL)))
10581 skip("Failed to create a D3D device, skipping tests.\n");
10582 IDirect3D9_Release(d3d);
10583 DestroyWindow(window);
10584 return;
10587 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
10588 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
10589 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
10591 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10592 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10593 memcpy(ptr, quad, sizeof(quad));
10594 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10595 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10596 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
10597 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
10598 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10599 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10601 hr = IDirect3DDevice9_BeginScene(device);
10602 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
10603 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
10604 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10605 hr = IDirect3DDevice9_EndScene(device);
10606 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
10608 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
10609 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10610 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10611 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10612 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10614 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
10615 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10616 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10617 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10618 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10620 refcount = IDirect3DVertexBuffer9_Release(buffer);
10621 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
10622 refcount = IDirect3DDevice9_Release(device);
10623 ok(!refcount, "Device has %u references left.\n", refcount);
10624 IDirect3D9_Release(d3d);
10625 DestroyWindow(window);
10628 static void test_lost_device(void)
10630 struct device_desc device_desc;
10631 IDirect3DDevice9 *device;
10632 IDirect3D9 *d3d;
10633 ULONG refcount;
10634 HWND window;
10635 HRESULT hr;
10636 BOOL ret;
10638 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10639 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10640 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10641 ok(!!d3d, "Failed to create a D3D object.\n");
10642 device_desc.device_window = window;
10643 device_desc.width = registry_mode.dmPelsWidth;
10644 device_desc.height = registry_mode.dmPelsHeight;
10645 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10646 if (!(device = create_device(d3d, window, &device_desc)))
10648 skip("Failed to create a D3D device, skipping tests.\n");
10649 goto done;
10652 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10653 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10654 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10655 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10657 ret = SetForegroundWindow(GetDesktopWindow());
10658 ok(ret, "Failed to set foreground window.\n");
10659 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10660 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10661 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10662 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10664 ret = ShowWindow(window, SW_RESTORE);
10665 ok(ret, "Failed to restore window.\n");
10666 ret = SetForegroundWindow(window);
10667 ok(ret, "Failed to set foreground window.\n");
10668 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10669 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
10670 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10671 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10673 hr = reset_device(device, &device_desc);
10674 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10675 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10676 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10677 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10678 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10680 device_desc.flags = 0;
10681 hr = reset_device(device, &device_desc);
10682 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10683 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10684 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10685 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10686 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10688 ret = SetForegroundWindow(GetDesktopWindow());
10689 ok(ret, "Failed to set foreground window.\n");
10690 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10691 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10692 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10693 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10695 ret = ShowWindow(window, SW_RESTORE);
10696 ok(ret, "Failed to restore window.\n");
10697 ret = SetForegroundWindow(window);
10698 ok(ret, "Failed to set foreground window.\n");
10699 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10700 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10701 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10702 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10704 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10705 hr = reset_device(device, &device_desc);
10706 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10707 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10708 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10709 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10710 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10712 ret = SetForegroundWindow(GetDesktopWindow());
10713 ok(ret, "Failed to set foreground window.\n");
10714 hr = reset_device(device, &device_desc);
10715 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10716 ret = ShowWindow(window, SW_RESTORE);
10717 ok(ret, "Failed to restore window.\n");
10718 ret = SetForegroundWindow(window);
10719 ok(ret, "Failed to set foreground window.\n");
10720 hr = reset_device(device, &device_desc);
10721 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10723 refcount = IDirect3DDevice9_Release(device);
10724 ok(!refcount, "Device has %u references left.\n", refcount);
10725 done:
10726 IDirect3D9_Release(d3d);
10727 DestroyWindow(window);
10730 static void test_resource_priority(void)
10732 IDirect3DDevice9 *device;
10733 IDirect3DSurface9 *surface;
10734 IDirect3DTexture9 *texture;
10735 IDirect3DVertexBuffer9 *buffer;
10736 IDirect3D9 *d3d;
10737 ULONG refcount;
10738 HWND window;
10739 HRESULT hr;
10740 static const struct
10742 D3DPOOL pool;
10743 const char *name;
10744 BOOL can_set_priority;
10746 test_data[] =
10748 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
10749 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
10750 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
10751 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
10753 unsigned int i;
10754 DWORD priority;
10756 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10757 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10758 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10759 ok(!!d3d, "Failed to create a D3D object.\n");
10760 if (!(device = create_device(d3d, window, NULL)))
10762 skip("Failed to create a D3D device, skipping tests.\n");
10763 IDirect3D9_Release(d3d);
10764 DestroyWindow(window);
10765 return;
10768 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
10770 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
10771 test_data[i].pool, &texture, NULL);
10772 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
10773 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10774 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10776 priority = IDirect3DTexture9_GetPriority(texture);
10777 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10778 priority = IDirect3DTexture9_SetPriority(texture, 1);
10779 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10780 priority = IDirect3DTexture9_GetPriority(texture);
10781 if (test_data[i].can_set_priority)
10783 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10784 priority = IDirect3DTexture9_SetPriority(texture, 2);
10785 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10787 else
10788 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10790 priority = IDirect3DSurface9_GetPriority(surface);
10791 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10792 priority = IDirect3DSurface9_SetPriority(surface, 1);
10793 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10794 priority = IDirect3DSurface9_GetPriority(surface);
10795 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10797 IDirect3DSurface9_Release(surface);
10798 IDirect3DTexture9_Release(texture);
10800 if (test_data[i].pool != D3DPOOL_MANAGED)
10802 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
10803 test_data[i].pool, &surface, NULL);
10804 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
10806 priority = IDirect3DSurface9_GetPriority(surface);
10807 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10808 priority = IDirect3DSurface9_SetPriority(surface, 1);
10809 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10810 priority = IDirect3DSurface9_GetPriority(surface);
10811 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10813 IDirect3DSurface9_Release(surface);
10816 if (test_data[i].pool != D3DPOOL_SCRATCH)
10818 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
10819 test_data[i].pool, &buffer, NULL);
10820 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
10822 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10823 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10824 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
10825 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10826 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10827 if (test_data[i].can_set_priority)
10829 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10830 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
10831 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10833 else
10834 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10836 IDirect3DVertexBuffer9_Release(buffer);
10840 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
10841 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
10843 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
10844 priority = IDirect3DSurface9_GetPriority(surface);
10845 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10846 priority = IDirect3DSurface9_SetPriority(surface, 1);
10847 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10848 priority = IDirect3DSurface9_GetPriority(surface);
10849 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10851 IDirect3DSurface9_Release(surface);
10853 refcount = IDirect3DDevice9_Release(device);
10854 ok(!refcount, "Device has %u references left.\n", refcount);
10855 IDirect3D9_Release(d3d);
10856 DestroyWindow(window);
10859 static void test_swapchain_parameters(void)
10861 IDirect3DDevice9 *device;
10862 IDirect3D9 *d3d;
10863 HWND window;
10864 HRESULT hr;
10865 unsigned int i;
10866 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
10867 IDirect3DSwapChain9 *swapchain;
10868 static const struct
10870 BOOL windowed;
10871 UINT backbuffer_count;
10872 D3DSWAPEFFECT swap_effect;
10873 HRESULT hr;
10875 tests[] =
10877 /* Swap effect 0 is not allowed. */
10878 {TRUE, 1, 0, D3DERR_INVALIDCALL},
10879 {FALSE, 1, 0, D3DERR_INVALIDCALL},
10881 /* All (non-ex) swap effects are allowed in
10882 * windowed and fullscreen mode. */
10883 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10884 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10885 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10886 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10887 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10889 /* Only one backbuffer in copy mode. */
10890 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
10891 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10892 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10893 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10895 /* Ok with the others, in fullscreen and windowed mode. */
10896 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
10897 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
10898 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
10899 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
10901 /* D3D9Ex swap effects. */
10902 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
10903 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
10904 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
10905 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
10906 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
10907 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
10909 /* 3 is the highest allowed backbuffer count. */
10910 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
10911 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
10912 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
10913 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
10914 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
10917 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10918 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10919 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10920 ok(!!d3d, "Failed to create a D3D object.\n");
10921 if (!(device = create_device(d3d, window, NULL)))
10923 skip("Failed to create a D3D device, skipping tests.\n");
10924 IDirect3D9_Release(d3d);
10925 DestroyWindow(window);
10926 return;
10928 IDirect3DDevice9_Release(device);
10930 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
10931 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
10932 present_parameters_windowed.hDeviceWindow = window;
10933 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
10934 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
10935 present_parameters_windowed.Windowed = TRUE;
10936 present_parameters_windowed.BackBufferCount = 1;
10938 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
10940 memset(&present_parameters, 0, sizeof(present_parameters));
10941 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
10942 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
10943 present_parameters.hDeviceWindow = window;
10944 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
10946 present_parameters.SwapEffect = tests[i].swap_effect;
10947 present_parameters.Windowed = tests[i].windowed;
10948 present_parameters.BackBufferCount = tests[i].backbuffer_count;
10950 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
10951 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
10952 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
10953 if (SUCCEEDED(hr))
10955 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
10957 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
10958 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
10960 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
10961 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
10962 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
10963 tests[i].swap_effect, present_parameters2.SwapEffect, i);
10964 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
10965 bb_count, present_parameters2.BackBufferCount, i);
10966 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
10967 tests[i].windowed, present_parameters2.Windowed, i);
10969 IDirect3DSwapChain9_Release(swapchain);
10970 IDirect3DDevice9_Release(device);
10973 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
10974 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
10975 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
10977 memset(&present_parameters, 0, sizeof(present_parameters));
10978 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
10979 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
10980 present_parameters.hDeviceWindow = window;
10981 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
10983 present_parameters.SwapEffect = tests[i].swap_effect;
10984 present_parameters.Windowed = tests[i].windowed;
10985 present_parameters.BackBufferCount = tests[i].backbuffer_count;
10987 hr = IDirect3DDevice9_Reset(device, &present_parameters);
10988 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
10990 if (FAILED(hr))
10992 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
10993 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
10995 IDirect3DDevice9_Release(device);
10998 IDirect3D9_Release(d3d);
10999 DestroyWindow(window);
11002 static void test_check_device_format(void)
11004 IDirect3D9 *d3d;
11005 HRESULT hr;
11007 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11008 ok(!!d3d, "Failed to create a D3D object.\n");
11010 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11011 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11013 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11015 else
11017 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11018 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11019 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11020 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11021 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11022 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11025 IDirect3D9_Release(d3d);
11028 static void test_miptree_layout(void)
11030 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11031 IDirect3DCubeTexture9 *texture_cube;
11032 IDirect3DTexture9 *texture_2d;
11033 IDirect3DDevice9 *device;
11034 D3DLOCKED_RECT map_desc;
11035 BYTE *base = NULL;
11036 IDirect3D9 *d3d;
11037 D3DCAPS9 caps;
11038 UINT refcount;
11039 HWND window;
11040 HRESULT hr;
11042 static const struct
11044 D3DFORMAT format;
11045 const char *name;
11047 formats[] =
11049 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11050 {D3DFMT_A8, "D3DFMT_A8"},
11051 {D3DFMT_L8, "D3DFMT_L8"},
11052 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11053 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11055 static const struct
11057 D3DPOOL pool;
11058 const char *name;
11060 pools[] =
11062 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11063 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11064 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11067 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11068 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11069 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11070 ok(!!d3d, "Failed to create a D3D object.\n");
11071 if (!(device = create_device(d3d, window, NULL)))
11073 skip("Failed to create a D3D device, skipping tests.\n");
11074 goto done;
11077 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11078 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11080 base_dimension = 257;
11081 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11083 skip("Using power of two base dimension.\n");
11084 base_dimension = 256;
11087 for (format_idx = 0; format_idx < sizeof(formats) / sizeof(*formats); ++format_idx)
11089 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11090 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11092 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11093 continue;
11096 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11098 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11099 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11100 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11101 pools[pool_idx].name, formats[format_idx].name, hr);
11103 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11104 for (i = 0, offset = 0; i < level_count; ++i)
11106 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11107 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11108 pools[pool_idx].name, formats[format_idx].name, i, hr);
11110 if (!i)
11111 base = map_desc.pBits;
11112 else
11113 ok(map_desc.pBits == base + offset,
11114 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11115 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11116 offset += (base_dimension >> i) * map_desc.Pitch;
11118 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11119 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11120 pools[pool_idx].name, formats[format_idx].name, i, hr);
11123 IDirect3DTexture9_Release(texture_2d);
11126 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11127 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11129 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11130 continue;
11133 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11135 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11136 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11137 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11138 pools[pool_idx].name, formats[format_idx].name, hr);
11140 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11141 for (i = 0, offset = 0; i < 6; ++i)
11143 for (j = 0; j < level_count; ++j)
11145 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11146 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11147 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11149 if (!i && !j)
11150 base = map_desc.pBits;
11151 else
11152 ok(map_desc.pBits == base + offset,
11153 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11154 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11155 offset += (base_dimension >> j) * map_desc.Pitch;
11157 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11158 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11159 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11161 offset = (offset + 15) & ~15;
11164 IDirect3DCubeTexture9_Release(texture_cube);
11168 refcount = IDirect3DDevice9_Release(device);
11169 ok(!refcount, "Device has %u references left.\n", refcount);
11170 done:
11171 IDirect3D9_Release(d3d);
11172 DestroyWindow(window);
11175 static void test_get_render_target_data(void)
11177 IDirect3DSurface9 *offscreen_surface, *render_target;
11178 IDirect3DDevice9 *device;
11179 IDirect3D9 *d3d;
11180 UINT refcount;
11181 HWND window;
11182 HRESULT hr;
11184 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11185 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11186 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11187 ok(!!d3d, "Failed to create a D3D object.\n");
11188 if (!(device = create_device(d3d, window, NULL)))
11190 skip("Failed to create a D3D device.\n");
11191 IDirect3D9_Release(d3d);
11192 DestroyWindow(window);
11193 return;
11196 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11197 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11198 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11200 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11201 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11202 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11204 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11205 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11207 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11208 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11210 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11211 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11213 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11214 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11216 IDirect3DSurface9_Release(render_target);
11217 IDirect3DSurface9_Release(offscreen_surface);
11218 refcount = IDirect3DDevice9_Release(device);
11219 ok(!refcount, "Device has %u references left.\n", refcount);
11220 IDirect3D9_Release(d3d);
11221 DestroyWindow(window);
11224 START_TEST(device)
11226 WNDCLASSA wc = {0};
11227 IDirect3D9 *d3d9;
11228 DEVMODEW current_mode;
11230 memset(&current_mode, 0, sizeof(current_mode));
11231 current_mode.dmSize = sizeof(current_mode);
11232 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
11233 registry_mode.dmSize = sizeof(registry_mode);
11234 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
11235 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
11236 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
11238 skip("Current mode does not match registry mode, skipping test.\n");
11239 return;
11242 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
11244 skip("could not create D3D9 object\n");
11245 return;
11247 IDirect3D9_Release(d3d9);
11249 wc.lpfnWndProc = DefWindowProcA;
11250 wc.lpszClassName = "d3d9_test_wc";
11251 RegisterClassA(&wc);
11253 test_get_set_vertex_declaration();
11254 test_get_declaration();
11255 test_fvf_decl_conversion();
11256 test_fvf_decl_management();
11257 test_vertex_declaration_alignment();
11258 test_unused_declaration_type();
11259 test_fpu_setup();
11260 test_multi_device();
11261 test_display_formats();
11262 test_display_modes();
11263 test_swapchain();
11264 test_refcount();
11265 test_mipmap_levels();
11266 test_checkdevicemultisampletype();
11267 test_invalid_multisample();
11268 test_cursor();
11269 test_cursor_pos();
11270 test_reset_fullscreen();
11271 test_reset();
11272 test_scene();
11273 test_limits();
11274 test_depthstenciltest();
11275 test_get_rt();
11276 test_draw_primitive();
11277 test_null_stream();
11278 test_lights();
11279 test_set_stream_source();
11280 test_scissor_size();
11281 test_wndproc();
11282 test_wndproc_windowed();
11283 test_window_style();
11284 test_mode_change();
11285 test_device_window_reset();
11286 test_reset_resources();
11287 test_set_rt_vp_scissor();
11288 test_volume_get_container();
11289 test_volume_resource();
11290 test_vb_lock_flags();
11291 test_vertex_buffer_alignment();
11292 test_query_support();
11293 test_occlusion_query_states();
11294 test_timestamp_query();
11295 test_get_set_vertex_shader();
11296 test_vertex_shader_constant();
11297 test_get_set_pixel_shader();
11298 test_pixel_shader_constant();
11299 test_unsupported_shaders();
11300 test_texture_stage_states();
11301 test_cube_textures();
11302 test_mipmap_gen();
11303 test_filter();
11304 test_get_set_texture();
11305 test_lod();
11306 test_surface_get_container();
11307 test_surface_alignment();
11308 test_lockrect_offset();
11309 test_lockrect_invalid();
11310 test_private_data();
11311 test_getdc();
11312 test_surface_dimensions();
11313 test_surface_format_null();
11314 test_surface_double_unlock();
11315 test_surface_blocks();
11316 test_set_palette();
11317 test_swvp_buffer();
11318 test_managed_buffer();
11319 test_npot_textures();
11320 test_vidmem_accounting();
11321 test_volume_locking();
11322 test_update_volumetexture();
11323 test_create_rt_ds_fail();
11324 test_volume_blocks();
11325 test_lockbox_invalid();
11326 test_shared_handle();
11327 test_pixel_format();
11328 test_begin_end_state_block();
11329 test_shader_constant_apply();
11330 test_vdecl_apply();
11331 test_resource_type();
11332 test_mipmap_lock();
11333 test_writeonly_resource();
11334 test_lost_device();
11335 test_resource_priority();
11336 test_swapchain_parameters();
11337 test_check_device_format();
11338 test_miptree_layout();
11339 test_get_render_target_data();
11341 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));