d3d9: Do not decrease swapchain refcount when it is already 0.
[wine.git] / dlls / d3d9 / tests / device.c
blob5aba575cc38c45a697880857ef8fcdfac6646e31
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);
1467 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1468 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1471 /* Render target and back buffer are identical. */
1472 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1473 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1474 if (pBackBuffer)
1476 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1477 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1478 pRenderTarget, pBackBuffer);
1479 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1480 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1481 pBackBuffer = NULL;
1483 CHECK_REFCOUNT(device, --refcount);
1485 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1486 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1487 CHECK_REFCOUNT(pSwapChain, 1);
1488 if (pStencilSurface)
1490 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1491 CHECK_REFCOUNT( pStencilSurface, 1);
1493 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1494 CHECK_REFCOUNT(device, refcount);
1495 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1496 CHECK_REFCOUNT(device, refcount);
1498 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1499 CHECK_REFCOUNT(device, --refcount);
1501 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1502 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1503 CHECK_REFCOUNT(device, ++refcount);
1504 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1505 CHECK_REFCOUNT(device, --refcount);
1506 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1507 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1508 pStencilSurface = NULL;
1511 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1512 CHECK_REFCOUNT(device, --refcount);
1513 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1514 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1516 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1517 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1518 CHECK_REFCOUNT(device, ++refcount);
1519 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1520 CHECK_REFCOUNT(device, --refcount);
1521 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1522 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1523 pSwapChain = NULL;
1526 /* Buffers */
1527 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1528 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1529 if(pIndexBuffer)
1531 tmp = get_refcount((IUnknown *)pIndexBuffer);
1533 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1534 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1535 hr = IDirect3DDevice9_SetIndices(device, NULL);
1536 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1539 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1540 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1541 if(pVertexBuffer)
1543 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1544 UINT offset = ~0;
1545 UINT stride = ~0;
1547 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1549 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1550 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1551 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1552 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1554 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1555 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1556 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1557 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1558 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1560 /* Shaders */
1561 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1562 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1563 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1564 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1565 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1566 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1567 /* Textures */
1568 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1569 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1570 if (pTexture)
1572 tmp = get_refcount( (IUnknown *)pTexture );
1574 /* SetTexture should not increase refcounts */
1575 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1576 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1577 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1578 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1580 /* This should not increment device refcount */
1581 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1582 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1583 /* But should increment texture's refcount */
1584 CHECK_REFCOUNT( pTexture, tmp+1 );
1585 /* Because the texture and surface refcount are identical */
1586 if (pTextureLevel)
1588 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1589 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1590 CHECK_REFCOUNT ( pTexture , tmp+2 );
1591 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1592 CHECK_REFCOUNT ( pTexture , tmp+1 );
1593 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1594 CHECK_REFCOUNT ( pTextureLevel, tmp );
1597 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1598 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1599 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1600 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1601 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1602 if (pVolumeTexture)
1604 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1606 /* This should not increment device refcount */
1607 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1608 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1609 /* But should increment volume texture's refcount */
1610 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1611 /* Because the volume texture and volume refcount are identical */
1612 if (pVolumeLevel)
1614 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1615 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1616 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1617 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1618 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1619 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1620 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1623 /* Surfaces */
1624 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1625 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1626 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1627 CHECK_REFCOUNT( pStencilSurface, 1 );
1628 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1629 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1630 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1631 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1632 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1633 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1634 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1635 CHECK_REFCOUNT( pRenderTarget3, 1 );
1636 /* Misc */
1637 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1638 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1640 memset(&d3dpp, 0, sizeof(d3dpp));
1641 d3dpp.Windowed = TRUE;
1642 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1643 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1644 d3dpp.EnableAutoDepthStencil = TRUE;
1645 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1646 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1647 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1648 if (pSwapChain)
1650 /* check implicit back buffer */
1651 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1652 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1653 CHECK_REFCOUNT(pSwapChain, 1);
1654 if (pBackBuffer)
1656 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1657 CHECK_REFCOUNT(pBackBuffer, 1);
1658 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1659 CHECK_REFCOUNT(device, --refcount);
1661 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1662 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1663 CHECK_REFCOUNT(device, ++refcount);
1664 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1665 CHECK_REFCOUNT(device, --refcount);
1666 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1667 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1668 pBackBuffer = NULL;
1670 CHECK_REFCOUNT(pSwapChain, 1);
1672 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1673 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1675 hr = IDirect3DDevice9_BeginStateBlock(device);
1676 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1677 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1678 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1680 /* The implicit render target is not freed if refcount reaches 0.
1681 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1682 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1683 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1684 if (pRenderTarget2)
1686 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1687 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1688 pRenderTarget, pRenderTarget2);
1689 CHECK_REFCOUNT(device, --refcount);
1690 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1691 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1692 pRenderTarget2 = NULL;
1694 pRenderTarget = NULL;
1696 cleanup:
1697 CHECK_RELEASE(device, device, --refcount);
1699 /* Buffers */
1700 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1701 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1702 /* Shaders */
1703 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1704 CHECK_RELEASE(pVertexShader, device, --refcount);
1705 CHECK_RELEASE(pPixelShader, device, --refcount);
1706 /* Textures */
1707 CHECK_RELEASE(pTextureLevel, device, --refcount);
1708 CHECK_RELEASE(pCubeTexture, device, --refcount);
1709 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1710 /* Surfaces */
1711 CHECK_RELEASE(pStencilSurface, device, --refcount);
1712 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1713 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1714 /* Misc */
1715 CHECK_RELEASE(pStateBlock, device, --refcount);
1716 CHECK_RELEASE(pSwapChain, device, --refcount);
1717 CHECK_RELEASE(pQuery, device, --refcount);
1718 /* This will destroy device - cannot check the refcount here */
1719 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1720 CHECK_RELEASE_REFCOUNT(d3d, 0);
1721 DestroyWindow(window);
1724 static void test_cursor(void)
1726 IDirect3DSurface9 *cursor = NULL;
1727 IDirect3DDevice9 *device;
1728 CURSORINFO info;
1729 IDirect3D9 *d3d;
1730 ULONG refcount;
1731 HCURSOR cur;
1732 HWND window;
1733 HRESULT hr;
1734 BOOL ret;
1736 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1737 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1738 ok(!!window, "Failed to create a window.\n");
1740 ret = SetCursorPos(50, 50);
1741 ok(ret, "Failed to set cursor position.\n");
1742 flush_events();
1743 memset(&info, 0, sizeof(info));
1744 info.cbSize = sizeof(info);
1745 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1746 cur = info.hCursor;
1748 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1749 ok(!!d3d, "Failed to create a D3D object.\n");
1750 if (!(device = create_device(d3d, window, NULL)))
1752 skip("Failed to create a 3D device, skipping test.\n");
1753 goto cleanup;
1756 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1757 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1758 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1760 /* Initially hidden */
1761 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1762 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1764 /* Not enabled without a surface*/
1765 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1766 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1768 /* Fails */
1769 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1770 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1772 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1773 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1775 IDirect3DSurface9_Release(cursor);
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); /* unchanged */
1783 /* Still hidden */
1784 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1785 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1787 /* Enabled now*/
1788 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1789 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1791 memset(&info, 0, sizeof(info));
1792 info.cbSize = sizeof(info);
1793 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1794 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1795 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1797 refcount = IDirect3DDevice9_Release(device);
1798 ok(!refcount, "Device has %u references left.\n", refcount);
1799 cleanup:
1800 IDirect3D9_Release(d3d);
1801 DestroyWindow(window);
1804 static void test_reset(void)
1806 HRESULT hr;
1807 RECT winrect;
1808 D3DPRESENT_PARAMETERS d3dpp;
1809 D3DDISPLAYMODE d3ddm, d3ddm2;
1810 D3DVIEWPORT9 vp;
1811 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1812 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1813 IDirect3DSurface9 *surface;
1814 IDirect3DTexture9 *texture;
1815 IDirect3DVertexShader9 *shader;
1816 UINT i, adapter_mode_count;
1817 D3DLOCKED_RECT lockrect;
1818 IDirect3DDevice9 *device1 = NULL;
1819 IDirect3DDevice9 *device2 = NULL;
1820 IDirect3DSwapChain9 *swapchain;
1821 struct device_desc device_desc;
1822 DEVMODEW devmode;
1823 IDirect3D9 *d3d;
1824 D3DCAPS9 caps;
1825 DWORD value;
1826 HWND hwnd;
1827 LONG ret;
1828 struct
1830 UINT w;
1831 UINT h;
1832 } *modes = NULL;
1833 UINT mode_count = 0;
1835 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1836 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1837 ok(!!hwnd, "Failed to create a window.\n");
1838 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1839 ok(!!d3d, "Failed to create a D3D object.\n");
1841 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1842 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1843 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1844 for(i = 0; i < adapter_mode_count; ++i)
1846 UINT j;
1847 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1848 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1849 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1851 for (j = 0; j < mode_count; ++j)
1853 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1854 break;
1856 if (j == mode_count)
1858 modes[j].w = d3ddm2.Width;
1859 modes[j].h = d3ddm2.Height;
1860 ++mode_count;
1863 /* We use them as invalid modes */
1864 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1865 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1866 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1867 d3ddm2.Width, d3ddm2.Height);
1868 goto cleanup;
1872 if (mode_count < 2)
1874 skip("Less than 2 modes supported, skipping mode tests\n");
1875 goto cleanup;
1878 i = 0;
1879 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1881 device_desc.width = modes[i].w;
1882 device_desc.height = modes[i].h;
1883 device_desc.device_window = hwnd;
1884 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1885 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1887 skip("Failed to create a D3D device, skipping tests.\n");
1888 goto cleanup;
1890 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1891 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1893 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1894 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1896 width = GetSystemMetrics(SM_CXSCREEN);
1897 height = GetSystemMetrics(SM_CYSCREEN);
1898 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1899 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1901 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1902 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1903 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1904 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1905 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1906 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1907 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1908 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1910 i = 1;
1911 vp.X = 10;
1912 vp.Y = 20;
1913 vp.MinZ = 2;
1914 vp.MaxZ = 3;
1915 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1916 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1918 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1919 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1920 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1921 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1922 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1924 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1925 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1926 d3dpp.Windowed = FALSE;
1927 d3dpp.BackBufferWidth = modes[i].w;
1928 d3dpp.BackBufferHeight = modes[i].h;
1929 d3dpp.BackBufferFormat = d3ddm.Format;
1930 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1931 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1932 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1933 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1935 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1936 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1937 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1939 ZeroMemory(&vp, sizeof(vp));
1940 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1941 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1942 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1943 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1944 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1945 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1946 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1947 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1949 width = GetSystemMetrics(SM_CXSCREEN);
1950 height = GetSystemMetrics(SM_CYSCREEN);
1951 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1952 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1954 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1955 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1956 memset(&d3dpp, 0, sizeof(d3dpp));
1957 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1958 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1959 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1960 d3dpp.BackBufferWidth, modes[i].w);
1961 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1962 d3dpp.BackBufferHeight, modes[i].h);
1963 IDirect3DSwapChain9_Release(swapchain);
1965 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1966 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1967 d3dpp.Windowed = TRUE;
1968 d3dpp.BackBufferWidth = 400;
1969 d3dpp.BackBufferHeight = 300;
1970 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1971 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1972 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1973 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1974 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1976 width = GetSystemMetrics(SM_CXSCREEN);
1977 height = GetSystemMetrics(SM_CYSCREEN);
1978 ok(width == orig_width, "Screen width is %d\n", width);
1979 ok(height == orig_height, "Screen height is %d\n", height);
1981 ZeroMemory(&vp, sizeof(vp));
1982 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1983 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1984 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1985 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1986 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1987 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1988 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1989 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1991 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1992 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1993 memset(&d3dpp, 0, sizeof(d3dpp));
1994 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1995 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1996 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1997 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1998 IDirect3DSwapChain9_Release(swapchain);
2000 memset(&devmode, 0, sizeof(devmode));
2001 devmode.dmSize = sizeof(devmode);
2002 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2003 devmode.dmPelsWidth = modes[1].w;
2004 devmode.dmPelsHeight = modes[1].h;
2005 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2006 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2007 width = GetSystemMetrics(SM_CXSCREEN);
2008 height = GetSystemMetrics(SM_CYSCREEN);
2009 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2010 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2012 d3dpp.BackBufferWidth = 500;
2013 d3dpp.BackBufferHeight = 400;
2014 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
2015 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2016 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed, hr %#x.\n", hr);
2017 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2018 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x.\n", hr);
2020 width = GetSystemMetrics(SM_CXSCREEN);
2021 height = GetSystemMetrics(SM_CYSCREEN);
2022 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2023 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2025 ZeroMemory(&vp, sizeof(vp));
2026 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2027 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed, hr %#x.\n", hr);
2028 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
2029 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
2030 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
2031 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
2032 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
2033 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
2035 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2036 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2037 memset(&d3dpp, 0, sizeof(d3dpp));
2038 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2039 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2040 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2041 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2042 IDirect3DSwapChain9_Release(swapchain);
2044 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2045 devmode.dmPelsWidth = orig_width;
2046 devmode.dmPelsHeight = orig_height;
2047 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2048 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2049 width = GetSystemMetrics(SM_CXSCREEN);
2050 height = GetSystemMetrics(SM_CYSCREEN);
2051 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
2052 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
2054 SetRect(&winrect, 0, 0, 200, 150);
2055 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
2056 ok(SetWindowPos(hwnd, NULL, 0, 0,
2057 winrect.right-winrect.left,
2058 winrect.bottom-winrect.top,
2059 SWP_NOMOVE|SWP_NOZORDER),
2060 "SetWindowPos failed\n");
2062 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2063 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2064 d3dpp.Windowed = TRUE;
2065 d3dpp.BackBufferWidth = 0;
2066 d3dpp.BackBufferHeight = 0;
2067 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
2068 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2069 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2070 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2071 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2073 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2074 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2075 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2076 d3dpp.BackBufferFormat, d3ddm.Format);
2077 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2078 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2079 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2080 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2081 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
2082 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2083 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2084 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2085 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2086 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2087 d3dpp.FullScreen_RefreshRateInHz);
2088 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2090 ZeroMemory(&vp, sizeof(vp));
2091 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2092 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
2093 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
2094 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
2095 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
2096 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
2097 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2098 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2100 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2101 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2102 memset(&d3dpp, 0, sizeof(d3dpp));
2103 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2104 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2105 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2106 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2107 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2108 d3dpp.BackBufferFormat, d3ddm.Format);
2109 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2110 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2111 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2112 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2113 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
2114 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2115 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2116 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2117 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2118 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2119 d3dpp.FullScreen_RefreshRateInHz);
2120 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2121 IDirect3DSwapChain9_Release(swapchain);
2123 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2124 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2125 d3dpp.Windowed = TRUE;
2126 d3dpp.BackBufferWidth = 400;
2127 d3dpp.BackBufferHeight = 300;
2129 /* _Reset fails if there is a resource in the default pool */
2130 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
2131 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2132 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2133 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2134 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2135 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2136 IDirect3DSurface9_Release(surface);
2137 /* Reset again to get the device out of the lost state */
2138 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2139 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2140 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2141 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2143 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
2145 IDirect3DVolumeTexture9 *volume_texture;
2147 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
2148 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
2149 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
2150 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2151 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2152 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2153 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
2154 hr, D3DERR_DEVICENOTRESET);
2155 IDirect3DVolumeTexture9_Release(volume_texture);
2156 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2157 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
2158 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2159 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2161 else
2163 skip("Volume textures not supported.\n");
2166 /* Scratch, sysmem and managed pools are fine */
2167 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2168 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2169 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2170 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2171 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2172 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2173 IDirect3DSurface9_Release(surface);
2175 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2176 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2177 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2178 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2179 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2180 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2181 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2182 IDirect3DSurface9_Release(surface);
2184 /* The depth stencil should get reset to the auto depth stencil when present. */
2185 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2186 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2188 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2189 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2190 ok(surface == NULL, "Depth stencil should be NULL\n");
2192 d3dpp.EnableAutoDepthStencil = TRUE;
2193 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2194 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2195 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2197 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2198 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2199 ok(surface != NULL, "Depth stencil should not be NULL\n");
2200 if (surface) IDirect3DSurface9_Release(surface);
2202 d3dpp.EnableAutoDepthStencil = FALSE;
2203 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2204 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2206 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2207 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2208 ok(surface == NULL, "Depth stencil should be NULL\n");
2210 /* Will a sysmem or scratch survive while locked */
2211 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2212 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2213 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2214 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2215 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2216 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2217 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2218 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2219 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2220 IDirect3DSurface9_UnlockRect(surface);
2221 IDirect3DSurface9_Release(surface);
2223 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2224 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2225 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2226 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2227 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2228 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2229 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2230 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2231 IDirect3DSurface9_UnlockRect(surface);
2232 IDirect3DSurface9_Release(surface);
2234 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2235 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2236 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2237 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2238 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2239 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2240 IDirect3DTexture9_Release(texture);
2242 /* A reference held to an implicit surface causes failures as well */
2243 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2244 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2245 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2246 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2247 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2248 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2249 IDirect3DSurface9_Release(surface);
2250 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2251 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2252 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2253 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2255 /* Shaders are fine as well */
2256 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2257 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2258 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2259 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2260 IDirect3DVertexShader9_Release(shader);
2262 /* Try setting invalid modes */
2263 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2264 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2265 d3dpp.Windowed = FALSE;
2266 d3dpp.BackBufferWidth = 32;
2267 d3dpp.BackBufferHeight = 32;
2268 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2269 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2270 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2271 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2273 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2274 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2275 d3dpp.Windowed = FALSE;
2276 d3dpp.BackBufferWidth = 801;
2277 d3dpp.BackBufferHeight = 600;
2278 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2279 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2280 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2281 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2283 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2284 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2285 d3dpp.Windowed = FALSE;
2286 d3dpp.BackBufferWidth = 0;
2287 d3dpp.BackBufferHeight = 0;
2288 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2289 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2290 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2291 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2293 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2295 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2296 d3dpp.Windowed = TRUE;
2297 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2298 d3dpp.BackBufferFormat = d3ddm.Format;
2299 d3dpp.EnableAutoDepthStencil = FALSE;
2300 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2302 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2303 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2305 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2306 goto cleanup;
2309 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2310 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2312 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2313 d3dpp.Windowed = TRUE;
2314 d3dpp.BackBufferWidth = 400;
2315 d3dpp.BackBufferHeight = 300;
2316 d3dpp.EnableAutoDepthStencil = TRUE;
2317 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2319 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2320 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2322 if (FAILED(hr)) goto cleanup;
2324 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2325 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2326 ok(surface != NULL, "Depth stencil should not be NULL\n");
2327 if (surface) IDirect3DSurface9_Release(surface);
2329 cleanup:
2330 HeapFree(GetProcessHeap(), 0, modes);
2331 if (device2)
2333 UINT refcount = IDirect3DDevice9_Release(device2);
2334 ok(!refcount, "Device has %u references left.\n", refcount);
2336 if (device1)
2338 UINT refcount = IDirect3DDevice9_Release(device1);
2339 ok(!refcount, "Device has %u references left.\n", refcount);
2341 IDirect3D9_Release(d3d);
2342 DestroyWindow(hwnd);
2345 /* Test adapter display modes */
2346 static void test_display_modes(void)
2348 D3DDISPLAYMODE dmode;
2349 IDirect3D9 *d3d;
2351 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2352 ok(!!d3d, "Failed to create a D3D object.\n");
2354 #define TEST_FMT(x,r) do { \
2355 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2356 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2357 } while(0)
2359 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2360 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2361 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2362 /* D3DFMT_R5G6B5 */
2363 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2364 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2365 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2366 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2367 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2368 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2369 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2370 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2371 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2372 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2373 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2374 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2376 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2377 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2379 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2380 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2381 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2383 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2384 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2385 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2386 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2387 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2388 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2390 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2391 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2392 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2393 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2394 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2395 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2396 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2397 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2398 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2399 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2401 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2402 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2403 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2404 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2405 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2406 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2407 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2408 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2409 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2410 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2412 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2413 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2414 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2415 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2416 /* Floating point formats */
2417 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2418 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2419 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2421 /* IEEE formats */
2422 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2423 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2424 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2426 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2428 TEST_FMT(0, D3DERR_INVALIDCALL);
2430 IDirect3D9_Release(d3d);
2433 static void test_scene(void)
2435 IDirect3DSurface9 *surface1, *surface2, *surface3;
2436 IDirect3DSurface9 *backBuffer, *rt, *ds;
2437 RECT rect = {0, 0, 128, 128};
2438 IDirect3DDevice9 *device;
2439 IDirect3D9 *d3d;
2440 ULONG refcount;
2441 D3DCAPS9 caps;
2442 HWND window;
2443 HRESULT hr;
2445 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2446 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2447 ok(!!window, "Failed to create a window.\n");
2448 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2449 ok(!!d3d, "Failed to create a D3D object.\n");
2450 if (!(device = create_device(d3d, window, NULL)))
2452 skip("Failed to create a 3D device, skipping test.\n");
2453 goto cleanup;
2456 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2457 memset(&caps, 0, sizeof(caps));
2458 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2459 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2461 /* Test an EndScene without BeginScene. Should return an error */
2462 hr = IDirect3DDevice9_EndScene(device);
2463 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2465 /* Test a normal BeginScene / EndScene pair, this should work */
2466 hr = IDirect3DDevice9_BeginScene(device);
2467 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2468 hr = IDirect3DDevice9_EndScene(device);
2469 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2471 /* Test another EndScene without having begun a new scene. Should return an error */
2472 hr = IDirect3DDevice9_EndScene(device);
2473 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2475 /* Two nested BeginScene and EndScene calls */
2476 hr = IDirect3DDevice9_BeginScene(device);
2477 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2478 hr = IDirect3DDevice9_BeginScene(device);
2479 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2480 hr = IDirect3DDevice9_EndScene(device);
2481 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2482 hr = IDirect3DDevice9_EndScene(device);
2483 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2485 /* Create some surfaces to test stretchrect between the scenes */
2486 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2487 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2488 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2489 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2490 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2491 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2492 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2493 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2494 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2495 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2496 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2497 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2499 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2500 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2501 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2502 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2504 /* First make sure a simple StretchRect call works */
2505 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2506 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2507 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2508 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2509 if (0) /* Disabled for now because it crashes in wine */
2511 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2512 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2513 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2516 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2517 * BeginScene - Endscene pair with normal surfaces and render targets, but
2518 * not depth stencil surfaces. */
2519 hr = IDirect3DDevice9_BeginScene(device);
2520 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2522 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2523 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2524 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2525 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2526 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2527 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2528 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2530 hr = IDirect3DDevice9_EndScene(device);
2531 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2533 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2534 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2535 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2537 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2538 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2539 hr = IDirect3DDevice9_BeginScene(device);
2540 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2541 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2542 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2543 hr = IDirect3DDevice9_EndScene(device);
2544 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2546 IDirect3DSurface9_Release(rt);
2547 IDirect3DSurface9_Release(ds);
2548 IDirect3DSurface9_Release(backBuffer);
2549 IDirect3DSurface9_Release(surface1);
2550 IDirect3DSurface9_Release(surface2);
2551 IDirect3DSurface9_Release(surface3);
2552 refcount = IDirect3DDevice9_Release(device);
2553 ok(!refcount, "Device has %u references left.\n", refcount);
2554 cleanup:
2555 IDirect3D9_Release(d3d);
2556 DestroyWindow(window);
2559 static void test_limits(void)
2561 IDirect3DTexture9 *texture;
2562 IDirect3DDevice9 *device;
2563 IDirect3D9 *d3d;
2564 unsigned int i;
2565 ULONG refcount;
2566 HWND window;
2567 HRESULT hr;
2569 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2570 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2571 ok(!!window, "Failed to create a window.\n");
2572 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2573 ok(!!d3d, "Failed to create a D3D object.\n");
2574 if (!(device = create_device(d3d, window, NULL)))
2576 skip("Failed to create a 3D device, skipping test.\n");
2577 goto cleanup;
2580 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2581 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2583 /* There are 16 pixel samplers. We should be able to access all of them */
2584 for (i = 0; i < 16; ++i)
2586 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2587 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2588 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2589 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2590 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2591 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2594 /* Now test all 8 textures stage states */
2595 for (i = 0; i < 8; ++i)
2597 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2598 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2601 /* Investigations show that accessing higher samplers / textures stage
2602 * states does not return an error either. Writing to too high samplers
2603 * (approximately sampler 40) causes memory corruption in Windows, so
2604 * there is no bounds checking. */
2605 IDirect3DTexture9_Release(texture);
2606 refcount = IDirect3D9_Release(device);
2607 ok(!refcount, "Device has %u references left.\n", refcount);
2608 cleanup:
2609 IDirect3D9_Release(d3d);
2610 DestroyWindow(window);
2613 static void test_depthstenciltest(void)
2615 HRESULT hr;
2616 IDirect3DDevice9 *pDevice = NULL;
2617 D3DPRESENT_PARAMETERS d3dpp;
2618 D3DDISPLAYMODE d3ddm;
2619 IDirect3DSurface9 *pDepthStencil = NULL;
2620 IDirect3DSurface9 *pDepthStencil2 = NULL;
2621 IDirect3D9 *d3d;
2622 DWORD state;
2623 HWND hwnd;
2625 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2626 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2627 ok(!!hwnd, "Failed to create a window.\n");
2628 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2629 ok(!!d3d, "Failed to create a D3D object.\n");
2631 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2632 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2633 d3dpp.Windowed = TRUE;
2634 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2635 d3dpp.BackBufferWidth = 800;
2636 d3dpp.BackBufferHeight = 600;
2637 d3dpp.BackBufferFormat = d3ddm.Format;
2638 d3dpp.EnableAutoDepthStencil = TRUE;
2639 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2641 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2642 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2643 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2644 if(!pDevice)
2646 skip("Failed to create a d3d device\n");
2647 goto cleanup;
2650 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2651 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2653 /* Try to clear */
2654 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2655 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2657 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2658 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2660 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2661 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2662 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2663 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2665 /* This left the render states untouched! */
2666 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2667 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2668 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2669 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2670 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2671 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2672 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2673 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2674 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2675 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2676 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2677 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2679 /* This is supposed to fail now */
2680 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2681 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2683 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2684 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2686 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2687 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2689 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2690 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2691 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2693 /* Now it works again */
2694 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2695 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2697 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2698 if(pDevice) IDirect3D9_Release(pDevice);
2700 /* Now see if autodepthstencil disable is honored. First, without a format set */
2701 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2702 d3dpp.Windowed = TRUE;
2703 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2704 d3dpp.BackBufferWidth = 800;
2705 d3dpp.BackBufferHeight = 600;
2706 d3dpp.BackBufferFormat = d3ddm.Format;
2707 d3dpp.EnableAutoDepthStencil = FALSE;
2708 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2710 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2711 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2712 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2713 if(!pDevice)
2715 skip("Failed to create a d3d device\n");
2716 goto cleanup;
2719 pDepthStencil = NULL;
2720 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2721 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2722 if(pDepthStencil) {
2723 IDirect3DSurface9_Release(pDepthStencil);
2724 pDepthStencil = NULL;
2727 /* Check the depth test state */
2728 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2729 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2730 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2732 if(pDevice) IDirect3D9_Release(pDevice);
2734 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2735 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2736 d3dpp.Windowed = TRUE;
2737 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2738 d3dpp.BackBufferWidth = 800;
2739 d3dpp.BackBufferHeight = 600;
2740 d3dpp.BackBufferFormat = d3ddm.Format;
2741 d3dpp.EnableAutoDepthStencil = FALSE;
2742 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2744 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2745 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2746 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2747 if(!pDevice)
2749 skip("Failed to create a d3d device\n");
2750 goto cleanup;
2753 pDepthStencil = NULL;
2754 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2755 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2756 if(pDepthStencil) {
2757 IDirect3DSurface9_Release(pDepthStencil);
2758 pDepthStencil = NULL;
2761 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2762 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2763 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2765 cleanup:
2766 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2767 if (pDevice)
2769 UINT refcount = IDirect3D9_Release(pDevice);
2770 ok(!refcount, "Device has %u references left.\n", refcount);
2772 IDirect3D9_Release(d3d);
2773 DestroyWindow(hwnd);
2776 static void test_get_rt(void)
2778 IDirect3DSurface9 *backbuffer, *rt;
2779 IDirect3DDevice9 *device;
2780 IDirect3D9 *d3d9;
2781 D3DCAPS9 caps;
2782 HWND window;
2783 HRESULT hr;
2784 ULONG ref;
2785 UINT i;
2787 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2788 0, 0, 128, 128, 0, 0, 0, 0);
2789 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2790 ok(!!d3d9, "Failed to create a D3D object.\n");
2791 device = create_device(d3d9, window, NULL);
2792 if (!device)
2794 skip("Failed to create a D3D device, skipping tests.\n");
2795 goto done;
2798 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2799 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2800 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2802 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2803 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2805 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2807 rt = backbuffer;
2808 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2809 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2810 ok(!rt, "Got rt %p.\n", rt);
2813 IDirect3DSurface9_Release(backbuffer);
2815 ref = IDirect3DDevice9_Release(device);
2816 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2817 done:
2818 IDirect3D9_Release(d3d9);
2819 DestroyWindow(window);
2822 static void test_draw_primitive(void)
2824 static const struct
2826 float position[3];
2827 DWORD color;
2829 quad[] =
2831 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2832 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2833 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2834 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2836 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
2837 static const D3DVERTEXELEMENT9 decl_elements[] =
2839 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2840 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2841 D3DDECL_END()
2844 IDirect3DVertexDeclaration9 *vertex_declaration;
2845 IDirect3DVertexBuffer9 *vertex_buffer;
2846 IDirect3DIndexBuffer9 *index_buffer;
2847 IDirect3DDevice9 *device;
2848 IDirect3D9 *d3d9;
2849 ULONG refcount;
2850 HWND window;
2851 HRESULT hr;
2852 void *ptr;
2854 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
2855 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2856 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2857 ok(!!d3d9, "Failed to create a D3D object.\n");
2858 if (!(device = create_device(d3d9, window, NULL)))
2860 skip("Failed to create a D3D device.\n");
2861 IDirect3D9_Release(d3d9);
2862 DestroyWindow(window);
2863 return;
2866 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2867 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
2869 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
2870 D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2871 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#x.\n", hr);
2872 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2873 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2874 memcpy(ptr, quad, sizeof(quad));
2875 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2876 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2877 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2878 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#x.\n", hr);
2880 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
2881 D3DPOOL_DEFAULT, &index_buffer, NULL);
2882 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#x.\n", hr);
2883 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2884 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2885 memcpy(ptr, indices, sizeof(indices));
2886 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2887 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2889 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2890 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#x.\n", hr);
2892 hr = IDirect3DDevice9_BeginScene(device);
2893 ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2895 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2896 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2898 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2899 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2901 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2902 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2904 hr = IDirect3DDevice9_SetIndices(device, NULL);
2905 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2906 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2907 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2908 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2910 /* Valid index buffer, NULL vertex declaration. Should fail */
2911 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2912 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2913 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2914 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2915 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2917 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2918 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2919 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2921 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2922 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2924 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2925 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2927 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2928 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2930 /* NULL index buffer, valid vertex vertex declaration. Should succeed */
2931 hr = IDirect3DDevice9_SetIndices(device, NULL);
2932 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2933 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2934 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2935 todo_wine ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2937 /* Valid index buffer and vertex declaration. Should succeed */
2938 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2939 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2940 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2941 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2942 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2944 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2945 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2946 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#x.\n", hr);
2948 hr = IDirect3DDevice9_EndScene(device);
2949 ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2951 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2952 ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2954 IDirect3DVertexBuffer9_Release(vertex_buffer);
2955 IDirect3DIndexBuffer9_Release(index_buffer);
2956 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2957 refcount = IDirect3DDevice9_Release(device);
2958 ok(!refcount, "Device has %u references left.\n", refcount);
2959 IDirect3D9_Release(d3d9);
2960 DestroyWindow(window);
2963 static void test_null_stream(void)
2965 IDirect3DVertexBuffer9 *buffer = NULL;
2966 IDirect3DDevice9 *device;
2967 IDirect3D9 *d3d9;
2968 ULONG refcount;
2969 HWND window;
2970 HRESULT hr;
2971 IDirect3DVertexShader9 *shader = NULL;
2972 IDirect3DVertexDeclaration9 *decl = NULL;
2973 static const DWORD shader_code[] =
2975 0xfffe0101, /* vs_1_1 */
2976 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2977 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2978 0x0000ffff /* end */
2980 static const D3DVERTEXELEMENT9 decl_elements[] = {
2981 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2982 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2983 D3DDECL_END()
2986 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2987 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2988 ok(!!window, "Failed to create a window.\n");
2989 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2990 ok(!!d3d9, "Failed to create a D3D object.\n");
2991 if (!(device = create_device(d3d9, window, NULL)))
2993 skip("Failed to create a 3D device, skipping test.\n");
2994 goto cleanup;
2997 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2998 if(FAILED(hr)) {
2999 skip("No vertex shader support\n");
3000 goto cleanup;
3002 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3003 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
3004 if (FAILED(hr)) {
3005 skip("Vertex declaration handling not possible.\n");
3006 goto cleanup;
3008 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
3009 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
3010 if (FAILED(hr)) {
3011 skip("Vertex buffer handling not possible.\n");
3012 goto cleanup;
3015 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
3016 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3017 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
3018 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3019 hr = IDirect3DDevice9_SetVertexShader(device, shader);
3020 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
3021 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3022 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
3024 hr = IDirect3DDevice9_BeginScene(device);
3025 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3026 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
3027 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3028 hr = IDirect3DDevice9_EndScene(device);
3029 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3031 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3032 IDirect3DDevice9_SetVertexShader(device, NULL);
3033 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3035 cleanup:
3036 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
3037 if (decl) IDirect3DVertexDeclaration9_Release(decl);
3038 if (shader) IDirect3DVertexShader9_Release(shader);
3039 if (device)
3041 refcount = IDirect3DDevice9_Release(device);
3042 ok(!refcount, "Device has %u references left.\n", refcount);
3044 IDirect3D9_Release(d3d9);
3045 DestroyWindow(window);
3048 static void test_lights(void)
3050 IDirect3DDevice9 *device;
3051 IDirect3D9 *d3d9;
3052 ULONG refcount;
3053 HWND window;
3054 HRESULT hr;
3055 unsigned int i;
3056 BOOL enabled;
3057 D3DCAPS9 caps;
3059 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3060 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3061 ok(!!window, "Failed to create a window.\n");
3062 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3063 ok(!!d3d9, "Failed to create a D3D object.\n");
3064 if (!(device = create_device(d3d9, window, NULL)))
3066 skip("Failed to create a 3D device, skipping test.\n");
3067 goto cleanup;
3070 memset(&caps, 0, sizeof(caps));
3071 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3072 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
3074 for(i = 1; i <= caps.MaxActiveLights; i++) {
3075 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
3076 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
3077 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
3078 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
3079 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
3082 /* TODO: Test the rendering results in this situation */
3083 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
3084 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
3085 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
3086 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
3087 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
3088 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
3089 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
3091 for(i = 1; i <= caps.MaxActiveLights; i++) {
3092 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
3093 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
3096 refcount = IDirect3DDevice9_Release(device);
3097 ok(!refcount, "Device has %u references left.\n", refcount);
3098 cleanup:
3099 IDirect3D9_Release(d3d9);
3100 DestroyWindow(window);
3103 static void test_set_stream_source(void)
3105 IDirect3DVertexBuffer9 *vb;
3106 IDirect3DDevice9 *device;
3107 IDirect3D9 *d3d9;
3108 ULONG refcount;
3109 HWND window;
3110 HRESULT hr;
3112 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3113 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3114 ok(!!window, "Failed to create a window.\n");
3115 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3116 ok(!!d3d9, "Failed to create a D3D object.\n");
3117 if (!(device = create_device(d3d9, window, NULL)))
3119 skip("Failed to create a 3D device, skipping test.\n");
3120 goto cleanup;
3123 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
3124 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
3126 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
3127 * (Radeon 9000 verified) reject them, so accept both results. Wine
3128 * currently rejects this to be able to optimize the vbo conversion, but
3129 * writes a WARN. */
3130 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
3131 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3132 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
3133 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3134 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
3135 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3136 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
3137 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3138 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
3139 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3141 /* Try to set the NULL buffer with an offset and stride 0 */
3142 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3143 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3144 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
3145 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3146 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
3147 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3148 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
3149 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3150 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
3151 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3153 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3154 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3156 IDirect3DVertexBuffer9_Release(vb);
3157 refcount = IDirect3DDevice9_Release(device);
3158 ok(!refcount, "Device has %u references left.\n", refcount);
3159 cleanup:
3160 IDirect3D9_Release(d3d9);
3161 DestroyWindow(window);
3164 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
3165 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
3166 * a fixed number of combinations are possible in fullscreen mode. In windowed
3167 * mode more combinations are allowed due to format conversion and this is
3168 * likely driver dependent. */
3169 static void test_display_formats(void)
3171 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
3172 unsigned int backbuffer, display;
3173 unsigned int windowed;
3174 IDirect3D9 *d3d9;
3175 BOOL should_pass;
3176 BOOL has_modes;
3177 HRESULT hr;
3179 static const struct
3181 const char *name;
3182 D3DFORMAT format;
3183 D3DFORMAT alpha_format;
3184 BOOL display;
3185 BOOL windowed;
3187 formats[] =
3189 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
3190 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
3191 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
3192 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
3193 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3194 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3195 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3198 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3199 ok(!!d3d9, "Failed to create a D3D object.\n");
3201 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
3203 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3205 for (windowed = 0; windowed <= 1; ++windowed)
3207 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
3209 should_pass = FALSE;
3211 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3213 D3DFORMAT backbuffer_format;
3215 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3216 backbuffer_format = formats[display].format;
3217 else
3218 backbuffer_format = formats[backbuffer].format;
3220 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3221 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3222 if (hr == D3D_OK)
3224 if (windowed)
3226 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3227 backbuffer_format, formats[display].format);
3228 should_pass = (hr == D3D_OK);
3230 else
3231 should_pass = (formats[display].format == formats[backbuffer].format
3232 || (formats[display].alpha_format
3233 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3237 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3238 formats[display].format, formats[backbuffer].format, windowed);
3239 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3240 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3241 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3246 IDirect3D9_Release(d3d9);
3249 static void test_scissor_size(void)
3251 struct device_desc device_desc;
3252 IDirect3D9 *d3d9_ptr;
3253 unsigned int i;
3254 static struct {
3255 int winx; int winy; int backx; int backy; DWORD flags;
3256 } scts[] = { /* scissor tests */
3257 {800, 600, 640, 480, 0},
3258 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3259 {640, 480, 800, 600, 0},
3260 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3263 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3264 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3266 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
3267 IDirect3DDevice9 *device_ptr = 0;
3268 HRESULT hr;
3269 HWND hwnd = 0;
3270 RECT scissorrect;
3272 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3273 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3275 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3277 scts[i].backx = registry_mode.dmPelsWidth;
3278 scts[i].backy = registry_mode.dmPelsHeight;
3281 device_desc.device_window = hwnd;
3282 device_desc.width = scts[i].backx;
3283 device_desc.height = scts[i].backy;
3284 device_desc.flags = scts[i].flags;
3285 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3287 skip("Failed to create a 3D device, skipping test.\n");
3288 DestroyWindow(hwnd);
3289 goto err_out;
3292 /* Check for the default scissor rect size */
3293 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3294 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3295 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3296 && scissorrect.top == 0 && scissorrect.left == 0,
3297 "Scissorrect mismatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3298 scts[i].backx, scts[i].backy);
3300 /* check the scissorrect values after a reset */
3301 device_desc.width = registry_mode.dmPelsWidth;
3302 device_desc.height = registry_mode.dmPelsHeight;
3303 device_desc.flags = scts[i].flags;
3304 hr = reset_device(device_ptr, &device_desc);
3305 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3306 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3307 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3309 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3310 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3311 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3312 && scissorrect.top == 0 && scissorrect.left == 0,
3313 "Scissorrect mismatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3314 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3316 if(device_ptr) {
3317 ULONG ref;
3319 ref = IDirect3DDevice9_Release(device_ptr);
3320 DestroyWindow(hwnd);
3321 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3325 err_out:
3326 IDirect3D9_Release(d3d9_ptr);
3329 static void test_multi_device(void)
3331 IDirect3DDevice9 *device1, *device2;
3332 HWND window1, window2;
3333 IDirect3D9 *d3d9;
3334 ULONG refcount;
3336 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3337 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3338 ok(!!window1, "Failed to create a window.\n");
3339 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3340 ok(!!d3d9, "Failed to create a D3D object.\n");
3341 if (!(device1 = create_device(d3d9, window1, NULL)))
3343 skip("Failed to create a 3D device, skipping test.\n");
3344 IDirect3D9_Release(d3d9);
3345 DestroyWindow(window1);
3346 return;
3348 IDirect3D9_Release(d3d9);
3350 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3351 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3352 ok(!!window2, "Failed to create a window.\n");
3353 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3354 ok(!!d3d9, "Failed to create a D3D object.\n");
3355 device2 = create_device(d3d9, window2, NULL);
3356 IDirect3D9_Release(d3d9);
3358 refcount = IDirect3DDevice9_Release(device2);
3359 ok(!refcount, "Device has %u references left.\n", refcount);
3360 refcount = IDirect3DDevice9_Release(device1);
3361 ok(!refcount, "Device has %u references left.\n", refcount);
3362 DestroyWindow(window2);
3363 DestroyWindow(window1);
3366 static HWND filter_messages;
3368 enum message_window
3370 DEVICE_WINDOW,
3371 FOCUS_WINDOW,
3374 struct message
3376 UINT message;
3377 enum message_window window;
3378 BOOL check_wparam;
3379 WPARAM expect_wparam;
3382 static const struct message *expect_messages;
3383 static HWND device_window, focus_window;
3384 static LONG windowposchanged_received, syscommand_received, wm_size_received;
3386 struct wndproc_thread_param
3388 HWND dummy_window;
3389 HANDLE window_created;
3390 HANDLE test_finished;
3391 BOOL running_in_foreground;
3394 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3396 if (filter_messages && filter_messages == hwnd)
3398 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3399 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3402 if (expect_messages)
3404 HWND w;
3406 switch (expect_messages->window)
3408 case DEVICE_WINDOW:
3409 w = device_window;
3410 break;
3412 case FOCUS_WINDOW:
3413 w = focus_window;
3414 break;
3416 default:
3417 w = NULL;
3418 break;
3421 if (hwnd == w && expect_messages->message == message)
3423 if (expect_messages->check_wparam)
3424 ok(wparam == expect_messages->expect_wparam,
3425 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3426 wparam, message, expect_messages->expect_wparam);
3428 ++expect_messages;
3432 /* KDE randomly does something with the hidden window during the
3433 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3434 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3435 * just flag WM_WINDOWPOSCHANGED as bad. */
3436 if (message == WM_WINDOWPOSCHANGED)
3437 InterlockedIncrement(&windowposchanged_received);
3438 else if (message == WM_SYSCOMMAND)
3439 InterlockedIncrement(&syscommand_received);
3440 else if (message == WM_SIZE)
3441 InterlockedIncrement(&wm_size_received);
3443 return DefWindowProcA(hwnd, message, wparam, lparam);
3446 static DWORD WINAPI wndproc_thread(void *param)
3448 struct wndproc_thread_param *p = param;
3449 DWORD res;
3450 BOOL ret;
3452 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3453 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3454 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3455 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3457 ret = SetEvent(p->window_created);
3458 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3460 for (;;)
3462 MSG msg;
3464 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3465 res = WaitForSingleObject(p->test_finished, 100);
3466 if (res == WAIT_OBJECT_0) break;
3467 if (res != WAIT_TIMEOUT)
3469 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3470 break;
3474 DestroyWindow(p->dummy_window);
3476 return 0;
3479 static void test_wndproc(void)
3481 struct wndproc_thread_param thread_params;
3482 struct device_desc device_desc;
3483 IDirect3DDevice9 *device;
3484 WNDCLASSA wc = {0};
3485 IDirect3D9 *d3d9;
3486 HANDLE thread;
3487 LONG_PTR proc;
3488 ULONG ref;
3489 DWORD res, tid;
3490 HWND tmp;
3491 UINT i, adapter_mode_count;
3492 HRESULT hr;
3493 D3DDISPLAYMODE d3ddm;
3494 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3495 DEVMODEW devmode;
3496 LONG change_ret;
3497 BOOL ret;
3499 static const struct message create_messages[] =
3501 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3502 /* Do not test wparam here. If device creation succeeds,
3503 * wparam is WA_ACTIVE. If device creation fails (testbot)
3504 * wparam is set to WA_INACTIVE on some Windows versions. */
3505 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3506 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3507 {0, 0, FALSE, 0},
3509 static const struct message focus_loss_messages[] =
3511 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3512 * not reliable on X11 WMs. When the window focus follows the
3513 * mouse pointer the message is not sent.
3514 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3515 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3516 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3517 * not deterministic. */
3518 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3519 /* Windows sends WM_ACTIVATE to the device window, indicating that
3520 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3521 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3522 * leaves the device window active, breaking re-activation in the
3523 * lost device test.
3524 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3525 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3526 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3527 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3528 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3529 * not deterministic. It may be sent after the focus window handling
3530 * or before. */
3531 {0, 0, FALSE, 0},
3533 static const struct message focus_loss_messages_nowc[] =
3535 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3536 * not reliable on X11 WMs. When the window focus follows the
3537 * mouse pointer the message is not sent.
3538 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3539 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3540 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3541 {0, 0, FALSE, 0},
3543 static const struct message reactivate_messages[] =
3545 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3546 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3547 /* optional WM_MOVE here if size changed */
3548 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3549 {0, 0, FALSE, 0},
3551 static const struct message reactivate_messages_nowc[] =
3553 /* We're activating the device window before activating the
3554 * focus window, so no ACTIVATEAPP message is sent. */
3555 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3556 {0, 0, FALSE, 0},
3558 static const struct message focus_loss_messages_hidden[] =
3560 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3561 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3562 {0, 0, FALSE, 0},
3564 static const struct message focus_loss_messages_filtered[] =
3566 /* WM_ACTIVATE is delivered to the window proc because it is
3567 * generated by SetForegroundWindow before the d3d routine
3568 * starts it work. Don't check for it due to focus-follows-mouse
3569 * WMs though. */
3570 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3571 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3572 {0, 0, FALSE, 0},
3574 static const struct message reactivate_messages_filtered[] =
3576 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3577 {0, 0, FALSE, 0},
3579 static const struct message sc_restore_messages[] =
3581 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3582 * processed it. Our wndproc has no way to prevent d3d from
3583 * handling the message. The second DefWindowProc call done by
3584 * our wndproc doesn't do any changes to the window because it
3585 * is already restored due to d3d's handling. */
3586 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3587 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3588 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3589 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3590 {0, 0, FALSE, 0},
3592 static const struct message sc_minimize_messages[] =
3594 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3595 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3596 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3597 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3598 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3599 {0, 0, FALSE, 0},
3601 static const struct message sc_maximize_messages[] =
3603 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3604 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3605 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3606 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3607 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3608 {0, 0, FALSE, 0},
3610 static const struct
3612 DWORD create_flags;
3613 const struct message *focus_loss_messages, *reactivate_messages;
3614 BOOL iconic;
3616 tests[] =
3618 {0, focus_loss_messages, reactivate_messages, TRUE},
3619 {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, reactivate_messages_nowc, FALSE},
3622 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3623 ok(!!d3d9, "Failed to create a D3D object.\n");
3625 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3626 for (i = 0; i < adapter_mode_count; ++i)
3628 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3629 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3631 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3632 continue;
3633 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3634 * refuses to create a device at these sizes. */
3635 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3636 continue;
3638 if (!user32_width)
3640 user32_width = d3ddm.Width;
3641 user32_height = d3ddm.Height;
3642 continue;
3645 /* Make sure the d3d mode is smaller in width or height and at most
3646 * equal in the other dimension than the mode passed to
3647 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3648 * the ChangeDisplaySettings parameters + 12. */
3649 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3650 continue;
3651 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3653 d3d_width = d3ddm.Width;
3654 d3d_height = d3ddm.Height;
3655 break;
3657 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3659 d3d_width = user32_width;
3660 d3d_height = user32_height;
3661 user32_width = d3ddm.Width;
3662 user32_height = d3ddm.Height;
3663 break;
3667 if (!d3d_width)
3669 skip("Could not find adequate modes, skipping mode tests.\n");
3670 IDirect3D9_Release(d3d9);
3671 return;
3674 wc.lpfnWndProc = test_proc;
3675 wc.lpszClassName = "d3d9_test_wndproc_wc";
3676 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3678 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3679 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3680 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3681 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3683 memset(&devmode, 0, sizeof(devmode));
3684 devmode.dmSize = sizeof(devmode);
3685 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
3687 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3688 devmode.dmPelsWidth = user32_width;
3689 devmode.dmPelsHeight = user32_height;
3690 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3691 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3693 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3694 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3695 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3696 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3697 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3698 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3700 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3701 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3703 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3704 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3705 (LONG_PTR)test_proc, proc);
3706 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3707 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3708 (LONG_PTR)test_proc, proc);
3710 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3711 device_window, focus_window, thread_params.dummy_window);
3713 tmp = GetFocus();
3714 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3715 if (thread_params.running_in_foreground)
3717 tmp = GetForegroundWindow();
3718 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3719 thread_params.dummy_window, tmp);
3721 else
3722 skip("Not running in foreground, skip foreground window test\n");
3724 flush_events();
3726 expect_messages = create_messages;
3728 device_desc.device_window = device_window;
3729 device_desc.width = d3d_width;
3730 device_desc.height = d3d_height;
3731 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3732 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3734 skip("Failed to create a D3D device, skipping tests.\n");
3735 goto done;
3738 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3739 expect_messages->message, expect_messages->window, i);
3740 expect_messages = NULL;
3742 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3744 tmp = GetFocus();
3745 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3746 tmp = GetForegroundWindow();
3747 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3749 SetForegroundWindow(focus_window);
3750 flush_events();
3752 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3753 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3754 (LONG_PTR)test_proc, proc, i);
3756 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3757 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3758 (LONG_PTR)test_proc, i);
3760 /* Change the mode while the device is in use and then drop focus. */
3761 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3762 devmode.dmPelsWidth = user32_width;
3763 devmode.dmPelsHeight = user32_height;
3764 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3765 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3767 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3768 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3769 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3770 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3771 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3772 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3774 expect_messages = tests[i].focus_loss_messages;
3775 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3776 * manually changing the focus. It generates the same messages, but the task
3777 * bar still shows the previous foreground window as active, and the window has
3778 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3779 * the device is difficult, see below. */
3780 SetForegroundWindow(GetDesktopWindow());
3781 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3782 expect_messages->message, expect_messages->window, i);
3783 expect_messages = NULL;
3784 tmp = GetFocus();
3785 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3786 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3788 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3789 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3791 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3792 ok(ret, "Failed to get display mode.\n");
3793 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3794 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3795 devmode.dmPelsWidth, devmode.dmPelsHeight);
3797 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3798 * done before the focus window is restored. This makes sense to some extent
3799 * because minimizing the window on focus loss is the application's job if this
3800 * flag is set. */
3801 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3803 ShowWindow(device_window, SW_MINIMIZE);
3804 ShowWindow(device_window, SW_RESTORE);
3806 flush_events();
3808 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3809 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3810 * restore is triggered by the user. */
3811 expect_messages = tests[i].reactivate_messages;
3812 ShowWindow(focus_window, SW_MINIMIZE);
3813 ShowWindow(focus_window, SW_RESTORE);
3814 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3815 SetForegroundWindow(focus_window);
3816 flush_events();
3817 SetForegroundWindow(focus_window);
3818 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3819 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3820 expect_messages->message, expect_messages->window, i);
3821 expect_messages = NULL;
3823 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3824 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3826 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3827 ok(ret, "Failed to get display mode.\n");
3828 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3829 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3830 devmode.dmPelsWidth, devmode.dmPelsHeight);
3832 hr = reset_device(device, &device_desc);
3833 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3835 ShowWindow(device_window, SW_HIDE);
3836 flush_events();
3838 expect_messages = focus_loss_messages_hidden;
3839 windowposchanged_received = 0;
3840 SetForegroundWindow(GetDesktopWindow());
3841 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3842 expect_messages->message, expect_messages->window, i);
3843 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3844 expect_messages = NULL;
3845 flush_events();
3847 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3848 ok(ret, "Failed to get display mode.\n");
3849 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3850 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3852 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3853 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3854 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3855 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3856 flush_events();
3858 syscommand_received = 0;
3859 expect_messages = sc_restore_messages;
3860 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3861 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3862 expect_messages->message, expect_messages->window, i);
3863 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3864 expect_messages = NULL;
3865 flush_events();
3867 expect_messages = sc_minimize_messages;
3868 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3869 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3870 expect_messages->message, expect_messages->window, i);
3871 expect_messages = NULL;
3872 flush_events();
3874 expect_messages = sc_maximize_messages;
3875 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3876 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3877 expect_messages->message, expect_messages->window, i);
3878 expect_messages = NULL;
3879 flush_events();
3881 SetForegroundWindow(GetDesktopWindow());
3882 ShowWindow(device_window, SW_MINIMIZE);
3883 ShowWindow(device_window, SW_RESTORE);
3884 ShowWindow(focus_window, SW_MINIMIZE);
3885 ShowWindow(focus_window, SW_RESTORE);
3886 SetForegroundWindow(focus_window);
3887 flush_events();
3889 /* Releasing a device in lost state breaks follow-up tests on native. */
3890 hr = reset_device(device, &device_desc);
3891 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3893 filter_messages = focus_window;
3895 ref = IDirect3DDevice9_Release(device);
3896 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3898 /* Fix up the mode until Wine's device release behavior is fixed. */
3899 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3900 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3902 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3903 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3904 (LONG_PTR)test_proc, proc, i);
3906 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3907 * on native in the test below. It isn't needed anyways. Creating the third
3908 * device will show it again. */
3909 filter_messages = NULL;
3910 ShowWindow(device_window, SW_HIDE);
3911 /* Remove the maximized state from the SYSCOMMAND test while we're not
3912 * interfering with a device. */
3913 ShowWindow(focus_window, SW_SHOWNORMAL);
3914 filter_messages = focus_window;
3916 device_desc.device_window = focus_window;
3917 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3919 skip("Failed to create a D3D device, skipping tests.\n");
3920 goto done;
3922 filter_messages = NULL;
3923 SetForegroundWindow(focus_window); /* For KDE. */
3924 flush_events();
3926 expect_messages = focus_loss_messages_filtered;
3927 windowposchanged_received = 0;
3928 SetForegroundWindow(GetDesktopWindow());
3929 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3930 expect_messages->message, expect_messages->window, i);
3931 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3932 expect_messages = NULL;
3934 /* The window is iconic even though no message was sent. */
3935 ok(!IsIconic(focus_window) == !tests[i].iconic,
3936 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
3938 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3939 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3941 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3942 ShowWindow(focus_window, SW_MINIMIZE);
3944 syscommand_received = 0;
3945 expect_messages = sc_restore_messages;
3946 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3947 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3948 expect_messages->message, expect_messages->window, i);
3949 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3950 expect_messages = NULL;
3951 flush_events();
3953 /* For FVWM. */
3954 ShowWindow(focus_window, SW_RESTORE);
3955 flush_events();
3957 expect_messages = sc_minimize_messages;
3958 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3959 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3960 expect_messages->message, expect_messages->window, i);
3961 expect_messages = NULL;
3962 flush_events();
3964 expect_messages = sc_maximize_messages;
3965 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
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 expect_messages = NULL;
3969 flush_events();
3971 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
3972 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
3973 SetForegroundWindow(GetDesktopWindow());
3974 flush_events();
3975 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
3976 flush_events();
3978 expect_messages = reactivate_messages_filtered;
3979 windowposchanged_received = 0;
3980 SetForegroundWindow(focus_window);
3981 flush_events();
3982 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3983 expect_messages->message, expect_messages->window, i);
3984 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
3985 ok(!windowposchanged_received || broken(1),
3986 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3987 expect_messages = NULL;
3989 filter_messages = focus_window;
3990 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3991 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3993 hr = reset_device(device, &device_desc);
3994 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3996 ref = IDirect3DDevice9_Release(device);
3997 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3999 device_desc.device_window = device_window;
4000 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4002 skip("Failed to create a D3D device, skipping tests.\n");
4003 goto done;
4006 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
4007 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
4008 (LONG_PTR)test_proc, i);
4010 ref = IDirect3DDevice9_Release(device);
4011 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4013 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4014 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4015 (LONG_PTR)DefWindowProcA, proc, i);
4017 done:
4018 filter_messages = NULL;
4019 DestroyWindow(device_window);
4020 DestroyWindow(focus_window);
4021 SetEvent(thread_params.test_finished);
4022 WaitForSingleObject(thread, INFINITE);
4023 CloseHandle(thread);
4026 IDirect3D9_Release(d3d9);
4027 CloseHandle(thread_params.test_finished);
4028 CloseHandle(thread_params.window_created);
4029 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4032 static void test_wndproc_windowed(void)
4034 struct wndproc_thread_param thread_params;
4035 struct device_desc device_desc;
4036 IDirect3DDevice9 *device;
4037 WNDCLASSA wc = {0};
4038 IDirect3D9 *d3d9;
4039 HANDLE thread;
4040 LONG_PTR proc;
4041 HRESULT hr;
4042 ULONG ref;
4043 DWORD res, tid;
4044 HWND tmp;
4046 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4047 ok(!!d3d9, "Failed to create a D3D object.\n");
4049 wc.lpfnWndProc = test_proc;
4050 wc.lpszClassName = "d3d9_test_wndproc_wc";
4051 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4053 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4054 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4055 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4056 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4058 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4059 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4060 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4061 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4062 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4063 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4064 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4065 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4067 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4068 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4070 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4071 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4072 (LONG_PTR)test_proc, proc);
4073 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4074 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4075 (LONG_PTR)test_proc, proc);
4077 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4078 device_window, focus_window, thread_params.dummy_window);
4080 tmp = GetFocus();
4081 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4082 if (thread_params.running_in_foreground)
4084 tmp = GetForegroundWindow();
4085 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4086 thread_params.dummy_window, tmp);
4088 else
4089 skip("Not running in foreground, skip foreground window test\n");
4091 filter_messages = focus_window;
4093 device_desc.device_window = device_window;
4094 device_desc.width = 640;
4095 device_desc.height = 480;
4096 device_desc.flags = 0;
4097 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4099 skip("Failed to create a D3D device, skipping tests.\n");
4100 goto done;
4103 tmp = GetFocus();
4104 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4105 tmp = GetForegroundWindow();
4106 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4107 thread_params.dummy_window, tmp);
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, got %#lx.\n",
4115 (LONG_PTR)test_proc, proc);
4117 filter_messages = NULL;
4119 device_desc.width = registry_mode.dmPelsWidth;
4120 device_desc.height = registry_mode.dmPelsHeight;
4121 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4122 hr = reset_device(device, &device_desc);
4123 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4125 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4126 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4127 (LONG_PTR)test_proc, proc);
4129 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4130 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4132 device_desc.flags = 0;
4133 hr = reset_device(device, &device_desc);
4134 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4136 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4137 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4138 (LONG_PTR)test_proc, proc);
4140 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4141 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4142 (LONG_PTR)test_proc, proc);
4144 filter_messages = focus_window;
4146 ref = IDirect3DDevice9_Release(device);
4147 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4149 filter_messages = device_window;
4151 device_desc.device_window = focus_window;
4152 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4154 skip("Failed to create a D3D device, skipping tests.\n");
4155 goto done;
4158 filter_messages = NULL;
4160 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4161 hr = reset_device(device, &device_desc);
4162 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4164 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4165 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4166 (LONG_PTR)test_proc, proc);
4168 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4169 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4171 device_desc.flags = 0;
4172 hr = reset_device(device, &device_desc);
4173 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4175 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4176 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4177 (LONG_PTR)test_proc, proc);
4179 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4180 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4181 (LONG_PTR)test_proc, proc);
4183 filter_messages = device_window;
4185 ref = IDirect3DDevice9_Release(device);
4186 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4188 device_desc.device_window = device_window;
4189 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4191 skip("Failed to create a D3D device, skipping tests.\n");
4192 goto done;
4195 filter_messages = NULL;
4197 device_desc.device_window = device_window;
4198 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4199 hr = reset_device(device, &device_desc);
4200 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4202 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4203 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4204 (LONG_PTR)test_proc, proc);
4206 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4207 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4209 device_desc.flags = 0;
4210 hr = reset_device(device, &device_desc);
4211 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4213 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4214 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4215 (LONG_PTR)test_proc, proc);
4217 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4218 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4219 (LONG_PTR)test_proc, proc);
4221 filter_messages = device_window;
4223 ref = IDirect3DDevice9_Release(device);
4224 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4226 done:
4227 filter_messages = NULL;
4228 IDirect3D9_Release(d3d9);
4230 SetEvent(thread_params.test_finished);
4231 WaitForSingleObject(thread, INFINITE);
4232 CloseHandle(thread_params.test_finished);
4233 CloseHandle(thread_params.window_created);
4234 CloseHandle(thread);
4236 DestroyWindow(device_window);
4237 DestroyWindow(focus_window);
4238 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4241 static void test_reset_fullscreen(void)
4243 struct device_desc device_desc;
4244 D3DDISPLAYMODE d3ddm, d3ddm2;
4245 unsigned int mode_count, i;
4246 IDirect3DDevice9 *device;
4247 WNDCLASSEXA wc = {0};
4248 IDirect3D9 *d3d;
4249 HRESULT hr;
4250 ATOM atom;
4251 static const struct message messages[] =
4253 /* Windows usually sends wparam = TRUE, except on the testbot,
4254 * where it randomly sends FALSE. Ignore it. */
4255 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4256 {0, 0, FALSE, 0},
4259 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4260 ok(!!d3d, "Failed to create a D3D object.\n");
4261 expect_messages = messages;
4263 wc.cbSize = sizeof(wc);
4264 wc.lpfnWndProc = test_proc;
4265 wc.lpszClassName = "test_reset_fullscreen";
4267 atom = RegisterClassExA(&wc);
4268 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4270 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4271 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4272 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4275 * Create a device in windowed mode.
4276 * Since the device is windowed and we haven't called any methods that
4277 * could show the window (such as ShowWindow or SetWindowPos) yet,
4278 * WM_ACTIVATEAPP will not have been sent.
4280 if (!(device = create_device(d3d, device_window, NULL)))
4282 skip("Unable to create device. Skipping test.\n");
4283 goto cleanup;
4287 * Switch to fullscreen mode.
4288 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4289 * message to be sent.
4291 device_desc.width = registry_mode.dmPelsWidth;
4292 device_desc.height = registry_mode.dmPelsHeight;
4293 device_desc.device_window = device_window;
4294 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4295 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4297 flush_events();
4298 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4299 expect_messages = NULL;
4301 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
4302 mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
4303 for (i = 0; i < mode_count; ++i)
4305 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
4306 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4308 if (d3ddm2.Width != d3ddm.Width || d3ddm2.Height != d3ddm.Height)
4309 break;
4311 if (i == mode_count)
4313 skip("Could not find a suitable display mode.\n");
4314 goto cleanup;
4317 wm_size_received = 0;
4319 /* Fullscreen mode change. */
4320 device_desc.width = d3ddm2.Width;
4321 device_desc.height = d3ddm2.Height;
4322 device_desc.device_window = device_window;
4323 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4324 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4326 flush_events();
4327 ok(!wm_size_received, "Received unexpected WM_SIZE message.\n");
4329 cleanup:
4330 if (device) IDirect3DDevice9_Release(device);
4331 IDirect3D9_Release(d3d);
4332 DestroyWindow(device_window);
4333 device_window = focus_window = NULL;
4334 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4338 static inline void set_fpu_cw(WORD cw)
4340 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4341 #define D3D9_TEST_SET_FPU_CW 1
4342 __asm__ volatile ("fnclex");
4343 __asm__ volatile ("fldcw %0" : : "m" (cw));
4344 #elif defined(__i386__) && defined(_MSC_VER)
4345 #define D3D9_TEST_SET_FPU_CW 1
4346 __asm fnclex;
4347 __asm fldcw cw;
4348 #endif
4351 static inline WORD get_fpu_cw(void)
4353 WORD cw = 0;
4354 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4355 #define D3D9_TEST_GET_FPU_CW 1
4356 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4357 #elif defined(__i386__) && defined(_MSC_VER)
4358 #define D3D9_TEST_GET_FPU_CW 1
4359 __asm fnstcw cw;
4360 #endif
4361 return cw;
4364 static WORD callback_cw, callback_set_cw;
4365 static DWORD callback_tid;
4367 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4369 *out = NULL;
4370 return E_NOINTERFACE;
4373 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4375 callback_cw = get_fpu_cw();
4376 set_fpu_cw(callback_set_cw);
4377 callback_tid = GetCurrentThreadId();
4378 return 2;
4381 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4383 callback_cw = get_fpu_cw();
4384 set_fpu_cw(callback_set_cw);
4385 callback_tid = GetCurrentThreadId();
4386 return 1;
4389 static const IUnknownVtbl dummy_object_vtbl =
4391 dummy_object_QueryInterface,
4392 dummy_object_AddRef,
4393 dummy_object_Release,
4396 static const GUID d3d9_private_data_test_guid =
4398 0xfdb37466,
4399 0x428f,
4400 0x4edf,
4401 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4404 static void test_fpu_setup(void)
4406 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4407 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
4408 IUnknown dummy_object = {&dummy_object_vtbl};
4409 struct device_desc device_desc;
4410 IDirect3DSurface9 *surface;
4411 IDirect3DDevice9 *device;
4412 WORD cw, expected_cw;
4413 HWND window = NULL;
4414 IDirect3D9 *d3d9;
4415 HRESULT hr;
4417 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4418 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4419 ok(!!window, "Failed to create a window.\n");
4420 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4421 ok(!!d3d9, "Failed to create a D3D object.\n");
4423 device_desc.device_window = window;
4424 device_desc.width = 640;
4425 device_desc.height = 480;
4426 device_desc.flags = 0;
4428 set_fpu_cw(0xf60);
4429 cw = get_fpu_cw();
4430 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4432 if (!(device = create_device(d3d9, window, &device_desc)))
4434 skip("Failed to create a 3D device, skipping test.\n");
4435 set_fpu_cw(0x37f);
4436 goto done;
4439 expected_cw = is_64bit ? 0xf60 : 0x7f;
4441 cw = get_fpu_cw();
4442 todo_wine_if(is_64bit)
4443 ok(cw == expected_cw, "cw is %#x, expected %#x.\n", cw, expected_cw);
4445 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4446 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4448 callback_set_cw = 0xf60;
4449 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4450 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4451 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4452 todo_wine_if(is_64bit)
4453 ok(callback_cw == expected_cw, "Callback cw is %#x, expected %#x.\n", callback_cw, expected_cw);
4454 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4455 cw = get_fpu_cw();
4456 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4458 callback_cw = 0;
4459 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4460 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4461 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4462 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4463 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4465 callback_set_cw = 0x7f;
4466 set_fpu_cw(0x7f);
4468 IDirect3DSurface9_Release(surface);
4470 callback_cw = 0;
4471 IDirect3DDevice9_Release(device);
4472 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4473 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4475 cw = get_fpu_cw();
4476 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4477 set_fpu_cw(0xf60);
4478 cw = get_fpu_cw();
4479 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4481 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4482 device = create_device(d3d9, window, &device_desc);
4483 ok(device != NULL, "CreateDevice failed.\n");
4485 cw = get_fpu_cw();
4486 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4488 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4489 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4491 callback_cw = 0;
4492 callback_set_cw = 0x37f;
4493 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4494 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4495 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4496 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4497 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4498 cw = get_fpu_cw();
4499 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4501 IDirect3DSurface9_Release(surface);
4503 callback_cw = 0;
4504 IDirect3DDevice9_Release(device);
4505 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4506 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4508 done:
4509 IDirect3D9_Release(d3d9);
4510 DestroyWindow(window);
4511 #endif
4514 static void test_window_style(void)
4516 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4517 LONG device_style, device_exstyle;
4518 LONG focus_style, focus_exstyle;
4519 struct device_desc device_desc;
4520 LONG style, expected_style;
4521 IDirect3DDevice9 *device;
4522 IDirect3D9 *d3d9;
4523 HRESULT hr;
4524 ULONG ref;
4525 BOOL ret;
4526 static const struct
4528 DWORD device_flags;
4529 LONG style, focus_loss_style, exstyle;
4531 tests[] =
4533 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4534 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4536 unsigned int i;
4538 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4539 ok(!!d3d9, "Failed to create a D3D object.\n");
4540 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4542 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
4544 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4545 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4546 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4547 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4549 device_style = GetWindowLongA(device_window, GWL_STYLE);
4550 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4551 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4552 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4554 GetWindowRect(focus_window, &focus_rect);
4555 GetWindowRect(device_window, &device_rect);
4557 device_desc.device_window = device_window;
4558 device_desc.width = registry_mode.dmPelsWidth;
4559 device_desc.height = registry_mode.dmPelsHeight;
4560 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4561 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4563 skip("Failed to create a D3D device, skipping tests.\n");
4564 DestroyWindow(device_window);
4565 DestroyWindow(focus_window);
4566 break;
4569 style = GetWindowLongA(device_window, GWL_STYLE);
4570 expected_style = device_style | tests[i].style;
4571 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4572 expected_style, style, i);
4573 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4574 expected_style = device_exstyle | tests[i].exstyle;
4575 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4576 expected_style, style, i);
4578 style = GetWindowLongA(focus_window, GWL_STYLE);
4579 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4580 focus_style, style, i);
4581 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4582 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4583 focus_exstyle, style, i);
4585 GetWindowRect(device_window, &r);
4586 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4587 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4588 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4589 else
4590 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4591 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4592 GetClientRect(device_window, &r2);
4593 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4594 GetWindowRect(focus_window, &r);
4595 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4596 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4598 device_desc.flags = 0;
4599 hr = reset_device(device, &device_desc);
4600 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4602 style = GetWindowLongA(device_window, GWL_STYLE);
4603 expected_style = device_style | tests[i].style;
4604 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4605 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4606 expected_style, style, i);
4607 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4608 expected_style = device_exstyle | tests[i].exstyle;
4609 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4610 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4611 expected_style, style, i);
4613 style = GetWindowLongA(focus_window, GWL_STYLE);
4614 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4615 focus_style, style, i);
4616 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4617 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4618 focus_exstyle, style, i);
4620 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4621 hr = reset_device(device, &device_desc);
4622 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4623 ret = SetForegroundWindow(GetDesktopWindow());
4624 ok(ret, "Failed to set foreground window.\n");
4626 style = GetWindowLongA(device_window, GWL_STYLE);
4627 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4628 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4629 expected_style, style);
4630 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4631 expected_style = device_exstyle | tests[i].exstyle;
4632 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4633 expected_style, style);
4635 style = GetWindowLongA(focus_window, GWL_STYLE);
4636 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4637 focus_style, style);
4638 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4639 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4640 focus_exstyle, style);
4642 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4643 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4644 * like a good idea to reset it first. */
4645 ShowWindow(focus_window, SW_MINIMIZE);
4646 ShowWindow(focus_window, SW_RESTORE);
4647 ret = SetForegroundWindow(focus_window);
4648 ok(ret, "Failed to set foreground window.\n");
4649 flush_events();
4650 hr = reset_device(device, &device_desc);
4651 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4653 ref = IDirect3DDevice9_Release(device);
4654 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4656 DestroyWindow(device_window);
4657 DestroyWindow(focus_window);
4659 IDirect3D9_Release(d3d9);
4662 static const POINT *expect_pos;
4664 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4666 if (message == WM_MOUSEMOVE)
4668 if (expect_pos && expect_pos->x && expect_pos->y)
4670 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4672 ClientToScreen(window, &p);
4673 if (expect_pos->x == p.x && expect_pos->y == p.y)
4674 ++expect_pos;
4678 return DefWindowProcA(window, message, wparam, lparam);
4681 static void test_cursor_pos(void)
4683 IDirect3DSurface9 *cursor;
4684 IDirect3DDevice9 *device;
4685 WNDCLASSA wc = {0};
4686 IDirect3D9 *d3d9;
4687 UINT refcount;
4688 HWND window;
4689 HRESULT hr;
4690 BOOL ret;
4692 /* Note that we don't check for movement we're not supposed to receive.
4693 * That's because it's hard to distinguish from the user accidentally
4694 * moving the mouse. */
4695 static const POINT points[] =
4697 {50, 50},
4698 {75, 75},
4699 {100, 100},
4700 {125, 125},
4701 {150, 150},
4702 {125, 125},
4703 {150, 150},
4704 {150, 150},
4705 {0, 0},
4708 wc.lpfnWndProc = test_cursor_proc;
4709 wc.lpszClassName = "d3d9_test_cursor_wc";
4710 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4711 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4712 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4713 ShowWindow(window, SW_SHOW);
4714 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4715 ok(!!d3d9, "Failed to create a D3D object.\n");
4717 device = create_device(d3d9, window, NULL);
4718 if (!device)
4720 skip("Failed to create a D3D device, skipping tests.\n");
4721 goto done;
4724 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4725 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4726 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4727 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4728 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4729 IDirect3DSurface9_Release(cursor);
4730 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4731 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4733 flush_events();
4734 expect_pos = points;
4736 ret = SetCursorPos(50, 50);
4737 ok(ret, "Failed to set cursor position.\n");
4738 flush_events();
4740 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4741 flush_events();
4742 /* SetCursorPosition() eats duplicates. */
4743 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4744 flush_events();
4746 ret = SetCursorPos(100, 100);
4747 ok(ret, "Failed to set cursor position.\n");
4748 flush_events();
4749 /* Even if the position was set with SetCursorPos(). */
4750 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4751 flush_events();
4753 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4754 flush_events();
4755 ret = SetCursorPos(150, 150);
4756 ok(ret, "Failed to set cursor position.\n");
4757 flush_events();
4758 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4759 flush_events();
4761 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4762 flush_events();
4763 /* SetCursorPos() doesn't. */
4764 ret = SetCursorPos(150, 150);
4765 ok(ret, "Failed to set cursor position.\n");
4766 flush_events();
4768 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4769 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4771 refcount = IDirect3DDevice9_Release(device);
4772 ok(!refcount, "Device has %u references left.\n", refcount);
4773 done:
4774 DestroyWindow(window);
4775 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4776 IDirect3D9_Release(d3d9);
4779 static void test_mode_change(void)
4781 RECT d3d_rect, focus_rect, r;
4782 struct device_desc device_desc;
4783 IDirect3DSurface9 *backbuffer;
4784 IDirect3DDevice9 *device;
4785 D3DSURFACE_DESC desc;
4786 IDirect3D9 *d3d9;
4787 DEVMODEW devmode;
4788 ULONG refcount;
4789 UINT adapter_mode_count, i;
4790 HRESULT hr;
4791 DWORD ret;
4792 LONG change_ret;
4793 D3DDISPLAYMODE d3ddm;
4794 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4796 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4797 ok(!!d3d9, "Failed to create a D3D object.\n");
4799 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4800 for (i = 0; i < adapter_mode_count; ++i)
4802 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4803 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4805 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4806 continue;
4807 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4808 * refuses to create a device at these sizes. */
4809 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4810 continue;
4812 if (!user32_width)
4814 user32_width = d3ddm.Width;
4815 user32_height = d3ddm.Height;
4816 continue;
4819 /* Make sure the d3d mode is smaller in width or height and at most
4820 * equal in the other dimension than the mode passed to
4821 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4822 * the ChangeDisplaySettings parameters + 12. */
4823 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4824 continue;
4825 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4827 d3d_width = d3ddm.Width;
4828 d3d_height = d3ddm.Height;
4829 break;
4831 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4833 d3d_width = user32_width;
4834 d3d_height = user32_height;
4835 user32_width = d3ddm.Width;
4836 user32_height = d3ddm.Height;
4837 break;
4841 if (!d3d_width)
4843 skip("Could not find adequate modes, skipping mode tests.\n");
4844 IDirect3D9_Release(d3d9);
4845 return;
4848 memset(&devmode, 0, sizeof(devmode));
4849 devmode.dmSize = sizeof(devmode);
4850 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4851 devmode.dmPelsWidth = user32_width;
4852 devmode.dmPelsHeight = user32_height;
4853 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4854 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4856 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4857 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4858 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4859 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4861 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4862 GetWindowRect(focus_window, &focus_rect);
4864 device_desc.device_window = device_window;
4865 device_desc.width = d3d_width;
4866 device_desc.height = d3d_height;
4867 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4868 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4870 skip("Failed to create a D3D device, skipping tests.\n");
4871 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4872 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4873 goto done;
4876 devmode.dmPelsWidth = user32_width;
4877 devmode.dmPelsHeight = user32_height;
4878 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4879 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4881 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4882 ok(ret, "Failed to get display mode.\n");
4883 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4884 "Expected resolution %ux%u, got %ux%u.\n",
4885 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4887 GetWindowRect(device_window, &r);
4888 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
4889 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
4890 GetWindowRect(focus_window, &r);
4891 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
4892 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
4894 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4895 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
4896 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
4897 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
4898 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4899 desc.Width, d3d_width);
4900 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4901 desc.Height, d3d_height);
4902 IDirect3DSurface9_Release(backbuffer);
4904 refcount = IDirect3DDevice9_Release(device);
4905 ok(!refcount, "Device has %u references left.\n", refcount);
4907 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4908 ok(ret, "Failed to get display mode.\n");
4909 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4910 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4911 "Expected resolution %ux%u, got %ux%u.\n",
4912 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4914 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4915 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4917 /* The mode restore also happens when the device was created at the original screen size. */
4919 device_desc.device_window = device_window;
4920 device_desc.width = registry_mode.dmPelsWidth;
4921 device_desc.height = registry_mode.dmPelsHeight;
4922 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4923 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4925 devmode.dmPelsWidth = user32_width;
4926 devmode.dmPelsHeight = user32_height;
4927 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4928 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4930 refcount = IDirect3DDevice9_Release(device);
4931 ok(!refcount, "Device has %u references left.\n", refcount);
4933 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4934 ok(ret, "Failed to get display mode.\n");
4935 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4936 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4937 "Expected resolution %ux%u, got %ux%u.\n",
4938 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4940 done:
4941 DestroyWindow(device_window);
4942 DestroyWindow(focus_window);
4943 IDirect3D9_Release(d3d9);
4946 static void test_device_window_reset(void)
4948 RECT fullscreen_rect, device_rect, r;
4949 struct device_desc device_desc;
4950 IDirect3DDevice9 *device;
4951 WNDCLASSA wc = {0};
4952 IDirect3D9 *d3d9;
4953 LONG_PTR proc;
4954 HRESULT hr;
4955 ULONG ref;
4957 wc.lpfnWndProc = test_proc;
4958 wc.lpszClassName = "d3d9_test_wndproc_wc";
4959 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4961 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4962 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4963 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4964 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4965 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4966 ok(!!d3d9, "Failed to create a D3D object.\n");
4968 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4969 GetWindowRect(device_window, &device_rect);
4971 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4972 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4973 (LONG_PTR)test_proc, proc);
4974 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4975 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4976 (LONG_PTR)test_proc, proc);
4978 device_desc.device_window = NULL;
4979 device_desc.width = registry_mode.dmPelsWidth;
4980 device_desc.height = registry_mode.dmPelsHeight;
4981 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4982 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4984 skip("Failed to create a D3D device, skipping tests.\n");
4985 goto done;
4988 GetWindowRect(focus_window, &r);
4989 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4990 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4991 GetWindowRect(device_window, &r);
4992 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
4993 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
4995 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4996 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4997 (LONG_PTR)test_proc, proc);
4998 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4999 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5001 device_desc.device_window = device_window;
5002 hr = reset_device(device, &device_desc);
5003 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5005 GetWindowRect(focus_window, &r);
5006 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5007 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5008 GetWindowRect(device_window, &r);
5009 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5010 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5012 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5013 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5014 (LONG_PTR)test_proc, proc);
5015 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5016 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5018 ref = IDirect3DDevice9_Release(device);
5019 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5021 done:
5022 IDirect3D9_Release(d3d9);
5023 DestroyWindow(device_window);
5024 DestroyWindow(focus_window);
5025 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
5028 static void test_reset_resources(void)
5030 IDirect3DSurface9 *surface, *rt;
5031 IDirect3DTexture9 *texture;
5032 IDirect3DDevice9 *device;
5033 IDirect3D9 *d3d9;
5034 unsigned int i;
5035 D3DCAPS9 caps;
5036 HWND window;
5037 HRESULT hr;
5038 ULONG ref;
5040 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5041 0, 0, 640, 480, 0, 0, 0, 0);
5042 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5043 ok(!!d3d9, "Failed to create a D3D object.\n");
5045 if (!(device = create_device(d3d9, window, NULL)))
5047 skip("Failed to create a D3D device, skipping tests.\n");
5048 goto done;
5051 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5052 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5054 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5055 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5056 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5057 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5058 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5059 IDirect3DSurface9_Release(surface);
5061 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5063 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5064 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5065 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5066 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5067 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5068 IDirect3DTexture9_Release(texture);
5069 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5070 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5071 IDirect3DSurface9_Release(surface);
5074 hr = reset_device(device, NULL);
5075 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5077 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5078 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5079 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5080 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5081 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5082 IDirect3DSurface9_Release(surface);
5083 IDirect3DSurface9_Release(rt);
5085 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5087 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5088 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5091 ref = IDirect3DDevice9_Release(device);
5092 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5094 done:
5095 IDirect3D9_Release(d3d9);
5096 DestroyWindow(window);
5099 static void test_set_rt_vp_scissor(void)
5101 IDirect3DStateBlock9 *stateblock;
5102 IDirect3DDevice9 *device;
5103 IDirect3DSurface9 *rt;
5104 IDirect3D9 *d3d9;
5105 D3DVIEWPORT9 vp;
5106 UINT refcount;
5107 HWND window;
5108 HRESULT hr;
5109 RECT rect;
5111 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5112 0, 0, 640, 480, 0, 0, 0, 0);
5113 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5114 ok(!!d3d9, "Failed to create a D3D object.\n");
5115 if (!(device = create_device(d3d9, window, NULL)))
5117 skip("Failed to create a D3D device, skipping tests.\n");
5118 DestroyWindow(window);
5119 return;
5122 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5123 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5124 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5126 hr = IDirect3DDevice9_GetViewport(device, &vp);
5127 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5128 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5129 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5130 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5131 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5132 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5133 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5135 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5136 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5137 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5138 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5140 hr = IDirect3DDevice9_BeginStateBlock(device);
5141 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5143 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5144 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5146 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5147 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5148 IDirect3DStateBlock9_Release(stateblock);
5150 hr = IDirect3DDevice9_GetViewport(device, &vp);
5151 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5152 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5153 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5154 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5155 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5156 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5157 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5159 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5160 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5161 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5162 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5164 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5165 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5167 vp.X = 10;
5168 vp.Y = 20;
5169 vp.Width = 30;
5170 vp.Height = 40;
5171 vp.MinZ = 0.25f;
5172 vp.MaxZ = 0.75f;
5173 hr = IDirect3DDevice9_SetViewport(device, &vp);
5174 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5176 SetRect(&rect, 50, 60, 70, 80);
5177 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5178 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5180 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5181 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5183 hr = IDirect3DDevice9_GetViewport(device, &vp);
5184 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5185 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5186 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5187 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5188 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5189 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5190 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5192 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5193 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5194 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5195 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5197 IDirect3DSurface9_Release(rt);
5198 refcount = IDirect3DDevice9_Release(device);
5199 ok(!refcount, "Device has %u references left.\n", refcount);
5200 IDirect3D9_Release(d3d9);
5201 DestroyWindow(window);
5204 static void test_volume_get_container(void)
5206 IDirect3DVolumeTexture9 *texture = NULL;
5207 IDirect3DVolume9 *volume = NULL;
5208 IDirect3DDevice9 *device;
5209 IUnknown *container;
5210 IDirect3D9 *d3d9;
5211 ULONG refcount;
5212 D3DCAPS9 caps;
5213 HWND window;
5214 HRESULT hr;
5216 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5217 0, 0, 640, 480, 0, 0, 0, 0);
5218 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5219 ok(!!d3d9, "Failed to create a D3D object.\n");
5220 if (!(device = create_device(d3d9, window, NULL)))
5222 skip("Failed to create a D3D device, skipping tests.\n");
5223 IDirect3D9_Release(d3d9);
5224 DestroyWindow(window);
5225 return;
5228 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5229 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5230 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5232 skip("No volume texture support, skipping tests.\n");
5233 IDirect3DDevice9_Release(device);
5234 IDirect3D9_Release(d3d9);
5235 DestroyWindow(window);
5236 return;
5239 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5240 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5241 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5242 ok(!!texture, "Got unexpected texture %p.\n", texture);
5244 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5245 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5246 ok(!!volume, "Got unexpected volume %p.\n", volume);
5248 /* These should work... */
5249 container = NULL;
5250 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5251 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5252 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5253 IUnknown_Release(container);
5255 container = NULL;
5256 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5257 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5258 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5259 IUnknown_Release(container);
5261 container = NULL;
5262 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5263 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5264 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5265 IUnknown_Release(container);
5267 container = NULL;
5268 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5269 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5270 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5271 IUnknown_Release(container);
5273 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5274 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5275 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5276 ok(!container, "Got unexpected container %p.\n", container);
5278 IDirect3DVolume9_Release(volume);
5279 IDirect3DVolumeTexture9_Release(texture);
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_volume_resource(void)
5288 IDirect3DVolumeTexture9 *texture;
5289 IDirect3DResource9 *resource;
5290 IDirect3DVolume9 *volume;
5291 IDirect3DDevice9 *device;
5292 IDirect3D9 *d3d9;
5293 ULONG refcount;
5294 D3DCAPS9 caps;
5295 HWND window;
5296 HRESULT hr;
5298 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5299 0, 0, 640, 480, 0, 0, 0, 0);
5300 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5301 ok(!!d3d9, "Failed to create a D3D object.\n");
5302 if (!(device = create_device(d3d9, window, NULL)))
5304 skip("Failed to create a D3D device, skipping tests.\n");
5305 IDirect3D9_Release(d3d9);
5306 DestroyWindow(window);
5307 return;
5310 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5311 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5312 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5314 skip("No volume texture support, skipping tests.\n");
5315 IDirect3DDevice9_Release(device);
5316 IDirect3D9_Release(d3d9);
5317 DestroyWindow(window);
5318 return;
5321 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5322 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5323 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5324 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5325 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5326 IDirect3DVolumeTexture9_Release(texture);
5328 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5329 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5331 IDirect3DVolume9_Release(volume);
5332 refcount = IDirect3DDevice9_Release(device);
5333 ok(!refcount, "Device has %u references left.\n", refcount);
5334 IDirect3D9_Release(d3d9);
5335 DestroyWindow(window);
5338 static void test_vb_lock_flags(void)
5340 static const struct
5342 DWORD flags;
5343 const char *debug_string;
5344 HRESULT win7_result;
5346 test_data[] =
5348 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5349 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5350 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5351 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5352 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5353 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5354 /* Completely bogus flags aren't an error. */
5355 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5357 IDirect3DVertexBuffer9 *buffer;
5358 IDirect3DDevice9 *device;
5359 IDirect3D9 *d3d9;
5360 unsigned int i;
5361 ULONG refcount;
5362 HWND window;
5363 HRESULT hr;
5364 void *data;
5366 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5367 0, 0, 640, 480, 0, 0, 0, 0);
5368 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5369 ok(!!d3d9, "Failed to create a D3D object.\n");
5370 if (!(device = create_device(d3d9, window, NULL)))
5372 skip("Failed to create a D3D device, skipping tests.\n");
5373 IDirect3D9_Release(d3d9);
5374 DestroyWindow(window);
5375 return;
5378 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5379 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5381 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5383 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5384 /* Windows XP always returns D3D_OK even with flags that don't make
5385 * sense. Windows 7 returns an error. At least one game (Shaiya)
5386 * depends on the Windows XP result, so mark the Windows 7 behavior as
5387 * broken. */
5388 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5389 hr, test_data[i].debug_string);
5390 if (SUCCEEDED(hr))
5392 ok(!!data, "Got unexpected data %p.\n", data);
5393 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5394 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5398 IDirect3DVertexBuffer9_Release(buffer);
5399 refcount = IDirect3DDevice9_Release(device);
5400 ok(!refcount, "Device has %u references left.\n", refcount);
5401 IDirect3D9_Release(d3d9);
5402 DestroyWindow(window);
5405 static const char *debug_d3dpool(D3DPOOL pool)
5407 switch (pool)
5409 case D3DPOOL_DEFAULT:
5410 return "D3DPOOL_DEFAULT";
5411 case D3DPOOL_SYSTEMMEM:
5412 return "D3DPOOL_SYSTEMMEM";
5413 case D3DPOOL_SCRATCH:
5414 return "D3DPOOL_SCRATCH";
5415 case D3DPOOL_MANAGED:
5416 return "D3DPOOL_MANAGED";
5417 default:
5418 return "unknown pool";
5422 static void test_vertex_buffer_alignment(void)
5424 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5425 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5426 IDirect3DVertexBuffer9 *buffer = NULL;
5427 const unsigned int align = 16;
5428 IDirect3DDevice9 *device;
5429 unsigned int i, j;
5430 IDirect3D9 *d3d9;
5431 ULONG refcount;
5432 HWND window;
5433 HRESULT hr;
5434 void *data;
5436 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5437 0, 0, 640, 480, 0, 0, 0, 0);
5438 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5439 ok(!!d3d9, "Failed to create a D3D object.\n");
5440 if (!(device = create_device(d3d9, window, NULL)))
5442 skip("Failed to create a D3D device, skipping tests.\n");
5443 IDirect3D9_Release(d3d9);
5444 DestroyWindow(window);
5445 return;
5448 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
5450 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5452 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5453 if (pools[j] == D3DPOOL_SCRATCH)
5454 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5455 else
5456 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5457 debug_d3dpool(pools[j]), sizes[i], hr);
5458 if (FAILED(hr))
5459 continue;
5461 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5462 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5463 ok(!((DWORD_PTR)data & (align - 1)),
5464 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5465 data, align, sizes[i], debug_d3dpool(pools[j]));
5466 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5467 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5468 IDirect3DVertexBuffer9_Release(buffer);
5472 refcount = IDirect3DDevice9_Release(device);
5473 ok(!refcount, "Device has %u references left.\n", refcount);
5474 IDirect3D9_Release(d3d9);
5475 DestroyWindow(window);
5478 static void test_query_support(void)
5480 static const D3DQUERYTYPE queries[] =
5482 D3DQUERYTYPE_VCACHE,
5483 D3DQUERYTYPE_RESOURCEMANAGER,
5484 D3DQUERYTYPE_VERTEXSTATS,
5485 D3DQUERYTYPE_EVENT,
5486 D3DQUERYTYPE_OCCLUSION,
5487 D3DQUERYTYPE_TIMESTAMP,
5488 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5489 D3DQUERYTYPE_TIMESTAMPFREQ,
5490 D3DQUERYTYPE_PIPELINETIMINGS,
5491 D3DQUERYTYPE_INTERFACETIMINGS,
5492 D3DQUERYTYPE_VERTEXTIMINGS,
5493 D3DQUERYTYPE_PIXELTIMINGS,
5494 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5495 D3DQUERYTYPE_CACHEUTILIZATION,
5497 IDirect3DQuery9 *query = NULL;
5498 IDirect3DDevice9 *device;
5499 IDirect3D9 *d3d9;
5500 unsigned int i;
5501 ULONG refcount;
5502 BOOL supported;
5503 HWND window;
5504 HRESULT hr;
5506 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5507 0, 0, 640, 480, 0, 0, 0, 0);
5508 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5509 ok(!!d3d9, "Failed to create a D3D object.\n");
5510 if (!(device = create_device(d3d9, window, NULL)))
5512 skip("Failed to create a D3D device, skipping tests.\n");
5513 IDirect3D9_Release(d3d9);
5514 DestroyWindow(window);
5515 return;
5518 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
5520 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5521 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5523 supported = hr == D3D_OK;
5525 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5526 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5528 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5529 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5531 if (query)
5533 IDirect3DQuery9_Release(query);
5534 query = NULL;
5538 refcount = IDirect3DDevice9_Release(device);
5539 ok(!refcount, "Device has %u references left.\n", refcount);
5540 IDirect3D9_Release(d3d9);
5541 DestroyWindow(window);
5544 static void test_occlusion_query(void)
5546 static const float quad[] =
5548 -1.0f, -1.0f, 0.0f,
5549 -1.0f, 1.0f, 0.0f,
5550 1.0f, 1.0f, 0.0f,
5551 1.0f, -1.0f, 0.0f,
5553 unsigned int data_size, i, count;
5554 struct device_desc device_desc;
5555 IDirect3DQuery9 *query = NULL;
5556 IDirect3DDevice9 *device;
5557 IDirect3DSurface9 *rt;
5558 IDirect3D9 *d3d9;
5559 D3DVIEWPORT9 vp;
5560 ULONG refcount;
5561 D3DCAPS9 caps;
5562 HWND window;
5563 HRESULT hr;
5564 union
5566 WORD word[4];
5567 DWORD dword[2];
5568 UINT64 uint;
5569 } data, expected;
5570 BOOL broken_occlusion = FALSE;
5571 expected.uint = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5573 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5574 0, 0, 640, 480, 0, 0, 0, 0);
5575 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5576 ok(!!d3d9, "Failed to create a D3D object.\n");
5577 device_desc.device_window = window;
5578 device_desc.width = registry_mode.dmPelsWidth;
5579 device_desc.height = registry_mode.dmPelsHeight;
5580 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5581 if (!(device = create_device(d3d9, window, &device_desc)))
5583 skip("Failed to create a D3D device, skipping tests.\n");
5584 IDirect3D9_Release(d3d9);
5585 DestroyWindow(window);
5586 return;
5589 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5590 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5591 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5592 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5593 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5594 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5596 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5597 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5598 if (!query)
5600 skip("Occlusion queries are not supported, skipping tests.\n");
5601 IDirect3DDevice9_Release(device);
5602 IDirect3D9_Release(d3d9);
5603 DestroyWindow(window);
5604 return;
5607 data_size = IDirect3DQuery9_GetDataSize(query);
5608 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5610 memset(&data, 0xff, sizeof(data));
5611 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5612 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5613 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5614 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5615 ok(data.dword[0] == 0xdddddddd && data.dword[1] == 0xffffffff,
5616 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5618 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5619 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5620 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5621 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5622 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5623 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5625 data.dword[0] = 0x12345678;
5626 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5627 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5628 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5629 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5630 if (hr == D3D_OK)
5631 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5633 hr = IDirect3DDevice9_BeginScene(device);
5634 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5635 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5636 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5637 hr = IDirect3DDevice9_EndScene(device);
5638 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5640 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5642 for (i = 0; i < 500; ++i)
5644 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5645 break;
5646 Sleep(10);
5648 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5650 memset(&data, 0xff, sizeof(data));
5651 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5652 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5653 ok(data.dword[0] == expected.dword[0] || broken(!data.dword[0]),
5654 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5655 if (!data.dword[0])
5657 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5658 broken_occlusion = TRUE;
5661 memset(&data, 0xff, sizeof(data));
5662 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5663 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5664 if (!broken_occlusion)
5665 ok(data.word[0] == expected.word[0],
5666 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5667 ok(data.word[1] == 0xffff,
5668 "Data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5670 memset(&data, 0xf0, sizeof(data));
5671 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5672 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5673 if (!broken_occlusion)
5674 ok(data.dword[0] == expected.dword[0],
5675 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5676 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5677 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5678 on AMD and Nvidia respectively). */
5679 if (0)
5681 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5682 data.dword[1]);
5685 memset(&data, 0xff, sizeof(data));
5686 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5687 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5688 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5690 /* This crashes on Windows. */
5691 if (0)
5693 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5694 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5697 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5698 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5699 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5700 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5701 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5702 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5704 if (broken_occlusion)
5705 goto done;
5707 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5708 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5710 vp.X = 0;
5711 vp.Y = 0;
5712 vp.Width = min(caps.MaxTextureWidth, 8192);
5713 vp.Height = min(caps.MaxTextureHeight, 8192);
5714 vp.MinZ = 0.0f;
5715 vp.MaxZ = 1.0f;
5716 hr = IDirect3DDevice9_SetViewport(device, &vp);
5717 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5719 hr = IDirect3DDevice9_CreateRenderTarget(device, vp.Width, vp.Height,
5720 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5721 if (FAILED(hr))
5723 skip("Failed to create render target (width %u, height %u), hr %#x.\n", vp.Width, vp.Height, hr);
5724 goto done;
5726 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5727 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5728 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5729 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
5730 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5732 expected.uint = vp.Width * vp.Height;
5733 count = ((((UINT64)~0u) + 1) / expected.uint) + 1;
5734 expected.uint *= count;
5736 trace("Expects 0x%08x%08x samples.\n", expected.dword[1], expected.dword[0]);
5738 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5739 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5740 hr = IDirect3DDevice9_BeginScene(device);
5741 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5742 for (i = 0; i < count; i++)
5744 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5745 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5747 hr = IDirect3DDevice9_EndScene(device);
5748 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5749 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5750 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5752 for (i = 0; i < 500; ++i)
5754 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5755 break;
5756 Sleep(10);
5758 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5760 memset(&data, 0xff, sizeof(data));
5761 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5762 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5763 ok((data.dword[0] == expected.dword[0] && data.dword[1] == expected.dword[1])
5764 || (data.dword[0] == 0xffffffff && !data.dword[1])
5765 || broken(data.dword[0] < 0xffffffff && !data.dword[1]),
5766 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5768 IDirect3DSurface9_Release(rt);
5770 done:
5771 IDirect3DQuery9_Release(query);
5772 refcount = IDirect3DDevice9_Release(device);
5773 ok(!refcount, "Device has %u references left.\n", refcount);
5774 IDirect3D9_Release(d3d9);
5775 DestroyWindow(window);
5778 static void test_timestamp_query(void)
5780 static const float quad[] =
5782 -1.0f, -1.0f, 0.0f,
5783 -1.0f, 1.0f, 0.0f,
5784 1.0f, 1.0f, 0.0f,
5785 1.0f, -1.0f, 0.0f,
5787 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5788 unsigned int data_size, i;
5789 IDirect3DDevice9 *device;
5790 IDirect3D9 *d3d9;
5791 ULONG refcount;
5792 HWND window;
5793 HRESULT hr;
5794 DWORD timestamp[2], freq[2];
5795 WORD disjoint[2];
5797 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5798 0, 0, 640, 480, 0, 0, 0, 0);
5799 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5800 ok(!!d3d9, "Failed to create a D3D object.\n");
5801 if (!(device = create_device(d3d9, window, NULL)))
5803 skip("Failed to create a D3D device, skipping tests.\n");
5804 IDirect3D9_Release(d3d9);
5805 DestroyWindow(window);
5806 return;
5809 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5810 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5811 if (FAILED(hr))
5813 skip("Timestamp queries are not supported, skipping tests.\n");
5814 IDirect3DDevice9_Release(device);
5815 IDirect3D9_Release(d3d9);
5816 DestroyWindow(window);
5817 return;
5819 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5820 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5822 memset(freq, 0xff, sizeof(freq));
5823 hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH);
5824 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5825 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5826 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5827 ok(freq[0] == 0xdddddddd && freq[1] == 0xffffffff,
5828 "Got unexpected query result 0x%08x%08x.\n", freq[1], freq[0]);
5830 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5831 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5832 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5833 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5835 memset(disjoint, 0xff, sizeof(disjoint));
5836 hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH);
5837 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5838 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5839 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5840 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xffff,
5841 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
5842 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(DWORD), D3DGETDATA_FLUSH);
5843 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5844 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xdddd,
5845 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
5847 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
5848 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5849 data_size = IDirect3DQuery9_GetDataSize(query);
5850 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5852 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
5853 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5854 for (i = 0; i < 500; ++i)
5856 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5857 break;
5858 Sleep(10);
5860 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5862 memset(freq, 0xff, sizeof(freq));
5863 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5864 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5865 ok(freq[1] == 0xffffffff,
5866 "Freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
5867 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
5868 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5869 ok(freq[1] != 0xffffffff, "High bytes of freq were not modified (0x%.8x).\n",
5870 freq[1]);
5872 memset(timestamp, 0xff, sizeof(timestamp));
5873 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5874 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5875 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5876 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5877 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xffffffff,
5878 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
5879 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5880 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5881 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xdddddddd,
5882 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
5884 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5885 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5886 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5887 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5888 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5889 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5891 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5892 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5894 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5895 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5896 hr = IDirect3DDevice9_BeginScene(device);
5897 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5898 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5899 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5900 hr = IDirect3DDevice9_EndScene(device);
5901 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5903 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5904 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5905 for (i = 0; i < 500; ++i)
5907 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5908 break;
5909 Sleep(10);
5911 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5913 memset(timestamp, 0xff, sizeof(timestamp));
5914 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5915 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5916 ok(timestamp[1] == 0xffffffff,
5917 "Timestamp was modified outside of the expected size (0x%.8x).\n",
5918 timestamp[1]);
5920 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5921 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5922 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5923 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5924 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5925 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5927 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5928 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5929 for (i = 0; i < 500; ++i)
5931 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5932 break;
5933 Sleep(10);
5935 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5937 memset(disjoint, 0xff, sizeof(disjoint));
5938 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5939 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5940 ok(disjoint[1] == 0xffff,
5941 "Disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
5942 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
5943 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5944 ok(disjoint[1] != 0xffff, "High bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
5946 /* It's not strictly necessary for the TIMESTAMP query to be inside
5947 * a TIMESTAMP_DISJOINT query. */
5948 hr = IDirect3DDevice9_BeginScene(device);
5949 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5950 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5951 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5952 hr = IDirect3DDevice9_EndScene(device);
5953 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5955 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5956 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5957 for (i = 0; i < 500; ++i)
5959 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5960 break;
5961 Sleep(10);
5963 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5964 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5965 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5967 IDirect3DQuery9_Release(query);
5968 IDirect3DQuery9_Release(disjoint_query);
5969 IDirect3DQuery9_Release(freq_query);
5970 refcount = IDirect3DDevice9_Release(device);
5971 ok(!refcount, "Device has %u references left.\n", refcount);
5972 IDirect3D9_Release(d3d9);
5973 DestroyWindow(window);
5976 static void test_get_set_vertex_shader(void)
5978 IDirect3DVertexShader9 *current_shader = NULL;
5979 IDirect3DVertexShader9 *shader = NULL;
5980 const IDirect3DVertexShader9Vtbl *shader_vtbl;
5981 IDirect3DDevice9 *device;
5982 ULONG refcount, i;
5983 IDirect3D9 *d3d;
5984 D3DCAPS9 caps;
5985 HWND window;
5986 HRESULT hr;
5988 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5989 0, 0, 640, 480, 0, 0, 0, 0);
5990 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5991 ok(!!d3d, "Failed to create a D3D object.\n");
5992 if (!(device = create_device(d3d, window, NULL)))
5994 skip("Failed to create a D3D device, skipping tests.\n");
5995 IDirect3D9_Release(d3d);
5996 DestroyWindow(window);
5997 return;
6000 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6001 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6002 if (!(caps.VertexShaderVersion & 0xffff))
6004 skip("No vertex shader support, skipping tests.\n");
6005 IDirect3DDevice9_Release(device);
6006 IDirect3D9_Release(d3d);
6007 DestroyWindow(window);
6008 return;
6011 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
6012 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6013 ok(!!shader, "Got unexpected shader %p.\n", shader);
6015 /* SetVertexShader() should not touch the shader's refcount. */
6016 i = get_refcount((IUnknown *)shader);
6017 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6018 refcount = get_refcount((IUnknown *)shader);
6019 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6020 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6022 /* GetVertexShader() should increase the shader's refcount by one. */
6023 i = refcount + 1;
6024 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
6025 refcount = get_refcount((IUnknown *)shader);
6026 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
6027 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6028 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6029 IDirect3DVertexShader9_Release(current_shader);
6031 /* SetVertexShader() with a bogus shader vtbl */
6032 shader_vtbl = shader->lpVtbl;
6033 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
6034 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6035 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6036 shader->lpVtbl = NULL;
6037 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6038 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6039 shader->lpVtbl = shader_vtbl;
6041 IDirect3DVertexShader9_Release(shader);
6042 refcount = IDirect3DDevice9_Release(device);
6043 ok(!refcount, "Device has %u references left.\n", refcount);
6044 IDirect3D9_Release(d3d);
6045 DestroyWindow(window);
6048 static void test_vertex_shader_constant(void)
6050 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};
6051 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6052 IDirect3DDevice9 *device;
6053 IDirect3D9 *d3d;
6054 ULONG refcount;
6055 D3DCAPS9 caps;
6056 DWORD consts;
6057 HWND window;
6058 HRESULT hr;
6060 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6061 0, 0, 640, 480, 0, 0, 0, 0);
6062 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6063 ok(!!d3d, "Failed to create a D3D object.\n");
6064 if (!(device = create_device(d3d, window, NULL)))
6066 skip("Failed to create a D3D device, skipping tests.\n");
6067 IDirect3D9_Release(d3d);
6068 DestroyWindow(window);
6069 return;
6072 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6073 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6074 if (!(caps.VertexShaderVersion & 0xffff))
6076 skip("No vertex shader support, skipping tests.\n");
6077 IDirect3DDevice9_Release(device);
6078 IDirect3D9_Release(d3d);
6079 DestroyWindow(window);
6080 return;
6082 consts = caps.MaxVertexShaderConst;
6084 /* A simple check that the stuff works at all. */
6085 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
6086 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6088 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
6089 * consts from MAX - 1. */
6090 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
6091 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6092 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6093 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6094 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6095 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6096 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6097 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6099 /* Constant -1. */
6100 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
6101 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6103 refcount = IDirect3DDevice9_Release(device);
6104 ok(!refcount, "Device has %u references left.\n", refcount);
6105 IDirect3D9_Release(d3d);
6106 DestroyWindow(window);
6109 static void test_get_set_pixel_shader(void)
6111 IDirect3DPixelShader9 *current_shader = NULL;
6112 IDirect3DPixelShader9 *shader = NULL;
6113 const IDirect3DPixelShader9Vtbl *shader_vtbl;
6114 IDirect3DDevice9 *device;
6115 ULONG refcount, i;
6116 IDirect3D9 *d3d;
6117 D3DCAPS9 caps;
6118 HWND window;
6119 HRESULT hr;
6121 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6122 0, 0, 640, 480, 0, 0, 0, 0);
6123 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6124 ok(!!d3d, "Failed to create a D3D object.\n");
6125 if (!(device = create_device(d3d, window, NULL)))
6127 skip("Failed to create a D3D device, skipping tests.\n");
6128 IDirect3D9_Release(d3d);
6129 DestroyWindow(window);
6130 return;
6133 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6134 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6135 if (!(caps.PixelShaderVersion & 0xffff))
6137 skip("No pixel shader support, skipping tests.\n");
6138 IDirect3DDevice9_Release(device);
6139 IDirect3D9_Release(d3d);
6140 DestroyWindow(window);
6141 return;
6144 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
6145 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6146 ok(!!shader, "Got unexpected shader %p.\n", shader);
6148 /* SetPixelShader() should not touch the shader's refcount. */
6149 i = get_refcount((IUnknown *)shader);
6150 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6151 refcount = get_refcount((IUnknown *)shader);
6152 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6153 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6155 /* GetPixelShader() should increase the shader's refcount by one. */
6156 i = refcount + 1;
6157 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6158 refcount = get_refcount((IUnknown *)shader);
6159 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6160 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6161 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6162 IDirect3DPixelShader9_Release(current_shader);
6164 /* SetPixelShader() with a bogus shader vtbl */
6165 shader_vtbl = shader->lpVtbl;
6166 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6167 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6168 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6169 shader->lpVtbl = NULL;
6170 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6171 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6172 shader->lpVtbl = shader_vtbl;
6174 IDirect3DPixelShader9_Release(shader);
6175 refcount = IDirect3DDevice9_Release(device);
6176 ok(!refcount, "Device has %u references left.\n", refcount);
6177 IDirect3D9_Release(d3d);
6178 DestroyWindow(window);
6181 static void test_pixel_shader_constant(void)
6183 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};
6184 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6185 IDirect3DDevice9 *device;
6186 DWORD consts = 0;
6187 IDirect3D9 *d3d;
6188 ULONG refcount;
6189 D3DCAPS9 caps;
6190 HWND window;
6191 HRESULT hr;
6193 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6194 0, 0, 640, 480, 0, 0, 0, 0);
6195 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6196 ok(!!d3d, "Failed to create a D3D object.\n");
6197 if (!(device = create_device(d3d, window, NULL)))
6199 skip("Failed to create a D3D device, skipping tests.\n");
6200 IDirect3D9_Release(d3d);
6201 DestroyWindow(window);
6202 return;
6205 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6206 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6207 if (!(caps.PixelShaderVersion & 0xffff))
6209 skip("No pixel shader support, skipping tests.\n");
6210 IDirect3DDevice9_Release(device);
6211 IDirect3D9_Release(d3d);
6212 DestroyWindow(window);
6213 return;
6216 /* A simple check that the stuff works at all. */
6217 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6218 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6220 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6221 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6222 consts = consts - 1;
6223 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6225 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6226 * pointless given the way the constant limit was determined. */
6227 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6228 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6230 /* Constant -1. */
6231 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6232 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6234 refcount = IDirect3DDevice9_Release(device);
6235 ok(!refcount, "Device has %u references left.\n", refcount);
6236 IDirect3D9_Release(d3d);
6237 DestroyWindow(window);
6240 static void test_unsupported_shaders(void)
6242 static const DWORD vs_3_0[] =
6244 0xfffe0300, /* vs_3_0 */
6245 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6246 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6247 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6248 0x0000ffff, /* end */
6251 #if 0
6252 float4 main(const float4 color : COLOR) : SV_TARGET
6254 float4 o;
6256 o = color;
6258 return o;
6260 #endif
6261 static const DWORD ps_4_0[] =
6263 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6264 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6265 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6266 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6267 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6268 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6269 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6270 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6271 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6272 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6273 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6274 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6275 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6276 0x00000000, 0x00000000, 0x00000000,
6278 #if 0
6279 vs_1_1
6280 dcl_position v0
6281 def c255, 1.0, 1.0, 1.0, 1.0
6282 add r0, v0, c255
6283 mov oPos, r0
6284 #endif
6285 static const DWORD vs_1_255[] =
6287 0xfffe0101,
6288 0x0000001f, 0x80000000, 0x900f0000,
6289 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6290 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6291 0x00000001, 0xc00f0000, 0x80e40000,
6292 0x0000ffff
6294 #if 0
6295 vs_1_1
6296 dcl_position v0
6297 def c256, 1.0, 1.0, 1.0, 1.0
6298 add r0, v0, c256
6299 mov oPos, r0
6300 #endif
6301 static const DWORD vs_1_256[] =
6303 0xfffe0101,
6304 0x0000001f, 0x80000000, 0x900f0000,
6305 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6306 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6307 0x00000001, 0xc00f0000, 0x80e40000,
6308 0x0000ffff
6310 #if 0
6311 vs_3_0
6312 dcl_position v0
6313 dcl_position o0
6314 def c256, 1.0, 1.0, 1.0, 1.0
6315 add r0, v0, c256
6316 mov o0, r0
6317 #endif
6318 static const DWORD vs_3_256[] =
6320 0xfffe0300,
6321 0x0200001f, 0x80000000, 0x900f0000,
6322 0x0200001f, 0x80000000, 0xe00f0000,
6323 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6324 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6325 0x02000001, 0xe00f0000, 0x80e40000,
6326 0x0000ffff
6328 #if 0
6329 /* This shader source generates syntax errors with the native shader assembler
6330 * due to the constant register index values.
6331 * The bytecode was modified by hand to use the intended values. */
6332 vs_3_0
6333 dcl_position v0
6334 dcl_position o0
6335 defi i16, 1, 1, 1, 1
6336 rep i16
6337 add r0, r0, v0
6338 endrep
6339 mov o0, r0
6340 #endif
6341 static const DWORD vs_3_i16[] =
6343 0xfffe0300,
6344 0x0200001f, 0x80000000, 0x900f0000,
6345 0x0200001f, 0x80000000, 0xe00f0000,
6346 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6347 0x01000026, 0xf0e40010,
6348 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6349 0x00000027,
6350 0x02000001, 0xe00f0000, 0x80e40000,
6351 0x0000ffff
6353 #if 0
6354 /* This shader source generates syntax errors with the native shader assembler
6355 * due to the constant register index values.
6356 * The bytecode was modified by hand to use the intended values. */
6357 vs_3_0
6358 dcl_position v0
6359 dcl_position o0
6360 defb b16, true
6361 mov r0, v0
6362 if b16
6363 add r0, r0, v0
6364 endif
6365 mov o0, r0
6366 #endif
6367 static const DWORD vs_3_b16[] =
6369 0xfffe0300,
6370 0x0200001f, 0x80000000, 0x900f0000,
6371 0x0200001f, 0x80000000, 0xe00f0000,
6372 0x0200002f, 0xe00f0810, 0x00000001,
6373 0x02000001, 0x800f0000, 0x90e40000,
6374 0x01000028, 0xe0e40810,
6375 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6376 0x0000002b,
6377 0x02000001, 0xe00f0000, 0x80e40000,
6378 0x0000ffff
6380 #if 0
6381 /* This shader source generates syntax errors with the native shader assembler
6382 * due to the constant register index values.
6383 * The bytecode was modified by hand to use the intended values. */
6384 ps_1_1
6385 def c8, 1.0, 1.0, 1.0, 1.0
6386 add r0, v0, c8
6387 #endif
6388 static const DWORD ps_1_8[] =
6390 0xffff0101,
6391 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6392 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6393 0x0000ffff
6395 #if 0
6396 /* This shader source generates syntax errors with the native shader assembler
6397 * due to the constant register index values.
6398 * The bytecode was modified by hand to use the intended values. */
6399 ps_2_0
6400 def c32, 1.0, 1.0, 1.0, 1.0
6401 add oC0, v0, c32
6402 #endif
6403 static const DWORD ps_2_32[] =
6405 0xffff0200,
6406 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6407 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6408 0x0000ffff
6410 #if 0
6411 /* This shader source generates syntax errors with the native shader assembler
6412 * due to the constant register index values.
6413 * The bytecode was modified by hand to use the intended values. */
6414 ps_3_0
6415 dcl_color0 v0
6416 def c224, 1.0, 1.0, 1.0, 1.0
6417 add oC0, v0, c224
6418 #endif
6419 static const DWORD ps_3_224[] =
6421 0xffff0300,
6422 0x0200001f, 0x8000000a, 0x900f0000,
6423 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6424 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6425 0x0000ffff
6427 #if 0
6428 /* This shader source generates syntax errors with the native shader assembler
6429 * due to the constant register index values.
6430 * The bytecode was modified by hand to use the intended values. */
6431 ps_2_0
6432 defb b0, true
6433 defi i0, 1, 1, 1, 1
6434 rep i0
6435 if b0
6436 add r0, r0, v0
6437 endif
6438 endrep
6439 mov oC0, r0
6440 #endif
6441 static const DWORD ps_2_0_boolint[] =
6443 0xffff0200,
6444 0x0200002f, 0xe00f0800, 0x00000001,
6445 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6446 0x01000026, 0xf0e40000,
6447 0x01000028, 0xe0e40800,
6448 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6449 0x0000002b,
6450 0x00000027,
6451 0x02000001, 0x800f0800, 0x80e40000,
6452 0x0000ffff
6455 IDirect3DVertexShader9 *vs = NULL;
6456 IDirect3DPixelShader9 *ps = NULL;
6457 IDirect3DDevice9 *device;
6458 IDirect3D9 * d3d;
6459 ULONG refcount;
6460 D3DCAPS9 caps;
6461 HWND window;
6462 HRESULT hr;
6464 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6465 0, 0, 640, 480, 0, 0, 0, 0);
6466 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6467 ok(!!d3d, "Failed to create a D3D object.\n");
6468 if (!(device = create_device(d3d, window, NULL)))
6470 skip("Failed to create a D3D device, skipping tests.\n");
6471 IDirect3D9_Release(d3d);
6472 DestroyWindow(window);
6473 return;
6476 /* These should always fail, regardless of supported shader version. */
6477 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6478 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6479 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6480 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6481 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6482 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6484 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6485 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6486 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6488 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6489 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6490 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6492 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6493 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6495 else
6497 skip("GPU supports SM2+, skipping SM1 test.\n");
6500 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6502 else
6504 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6506 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6507 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6508 IDirect3DVertexShader9_Release(vs);
6509 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6510 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6511 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6512 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6513 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6514 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6515 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6516 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6519 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6521 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6522 goto cleanup;
6524 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6525 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6526 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6527 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6528 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6529 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6530 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6531 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6532 if (ps)
6533 IDirect3DPixelShader9_Release(ps);
6535 cleanup:
6536 refcount = IDirect3DDevice9_Release(device);
6537 ok(!refcount, "Device has %u references left.\n", refcount);
6538 IDirect3D9_Release(d3d);
6539 DestroyWindow(window);
6542 /* Test the default texture stage state values */
6543 static void test_texture_stage_states(void)
6545 IDirect3DDevice9 *device;
6546 IDirect3D9 *d3d;
6547 unsigned int i;
6548 ULONG refcount;
6549 D3DCAPS9 caps;
6550 DWORD value;
6551 HWND window;
6552 HRESULT hr;
6554 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6555 0, 0, 640, 480, 0, 0, 0, 0);
6556 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6557 ok(!!d3d, "Failed to create a D3D object.\n");
6558 if (!(device = create_device(d3d, window, NULL)))
6560 skip("Failed to create a D3D device, skipping tests.\n");
6561 IDirect3D9_Release(d3d);
6562 DestroyWindow(window);
6563 return;
6566 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6567 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6569 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6571 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6572 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6573 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6574 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6575 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6576 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6577 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6578 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6579 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6580 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6581 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6582 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6583 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6584 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6585 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6586 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6587 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6588 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6589 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6590 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6591 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6592 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6593 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6594 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6595 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6596 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6597 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6598 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6599 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6600 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6601 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6602 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6603 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6604 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6605 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6606 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6607 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6608 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6609 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6610 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6611 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6612 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6613 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6614 ok(value == D3DTTFF_DISABLE,
6615 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6616 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6617 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6618 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6619 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6620 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6621 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6622 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6623 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6624 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6625 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6626 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6627 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6630 refcount = IDirect3DDevice9_Release(device);
6631 ok(!refcount, "Device has %u references left.\n", refcount);
6632 IDirect3D9_Release(d3d);
6633 DestroyWindow(window);
6636 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6638 IDirect3DCubeTexture9 *texture;
6639 IDirect3D9 *d3d;
6640 HRESULT hr;
6642 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6643 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6644 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6645 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6646 IDirect3D9_Release(d3d);
6647 if (FAILED(hr))
6649 skip("No cube mipmap generation support, skipping tests.\n");
6650 return;
6653 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6654 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6655 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6656 IDirect3DCubeTexture9_Release(texture);
6658 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6659 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6660 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6661 IDirect3DCubeTexture9_Release(texture);
6664 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6666 IDirect3DCubeTexture9 *texture;
6667 IDirect3DSurface9 *surface;
6668 D3DSURFACE_DESC desc;
6669 DWORD levels;
6670 HRESULT hr;
6671 D3DCAPS9 caps;
6673 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6674 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6675 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6676 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6678 skip("Failed to create cube texture, skipping tests.\n");
6679 return;
6682 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6683 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6684 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6685 else
6686 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6688 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6689 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6690 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6691 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6692 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6693 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6695 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6696 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6697 IDirect3DSurface9_Release(surface);
6698 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6699 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6700 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6701 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6703 IDirect3DCubeTexture9_Release(texture);
6706 static void test_cube_textures(void)
6708 IDirect3DCubeTexture9 *texture;
6709 IDirect3DDevice9 *device;
6710 IDirect3D9 *d3d;
6711 ULONG refcount;
6712 D3DCAPS9 caps;
6713 HWND window;
6714 HRESULT hr;
6716 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6717 0, 0, 640, 480, 0, 0, 0, 0);
6718 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6719 ok(!!d3d, "Failed to create a D3D object.\n");
6720 if (!(device = create_device(d3d, window, NULL)))
6722 skip("Failed to create a D3D device, skipping tests.\n");
6723 IDirect3D9_Release(d3d);
6724 DestroyWindow(window);
6725 return;
6728 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6729 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6731 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
6733 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6734 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
6735 IDirect3DCubeTexture9_Release(texture);
6736 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6737 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
6738 IDirect3DCubeTexture9_Release(texture);
6739 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6740 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
6741 IDirect3DCubeTexture9_Release(texture);
6743 else
6745 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6746 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
6747 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6748 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
6749 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6750 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
6752 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
6753 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
6754 IDirect3DCubeTexture9_Release(texture);
6756 test_cube_texture_mipmap_gen(device);
6757 test_cube_texture_levels(device);
6759 refcount = IDirect3DDevice9_Release(device);
6760 ok(!refcount, "Device has %u references left.\n", refcount);
6761 IDirect3D9_Release(d3d);
6762 DestroyWindow(window);
6765 static void test_mipmap_gen(void)
6767 D3DTEXTUREFILTERTYPE filter_type;
6768 IDirect3DTexture9 *texture;
6769 IDirect3DSurface9 *surface;
6770 IDirect3DDevice9 *device;
6771 D3DSURFACE_DESC desc;
6772 D3DLOCKED_RECT lr;
6773 IDirect3D9 *d3d;
6774 ULONG refcount;
6775 unsigned int i;
6776 DWORD levels;
6777 HWND window;
6778 HRESULT hr;
6780 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6781 ok(!!d3d, "Failed to create a D3D object.\n");
6783 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6784 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
6786 skip("No mipmap generation support, skipping tests.\n");
6787 IDirect3D9_Release(d3d);
6788 return;
6791 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6792 0, 0, 640, 480, 0, 0, 0, 0);
6793 if (!(device = create_device(d3d, window, NULL)))
6795 skip("Failed to create a D3D device, skipping tests.\n");
6796 IDirect3D9_Release(d3d);
6797 DestroyWindow(window);
6798 return;
6801 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6802 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6803 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6804 IDirect3DTexture9_Release(texture);
6806 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6807 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6808 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6810 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6811 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
6812 "Got unexpected filter_type %#x.\n", filter_type);
6813 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
6814 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6815 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
6816 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6817 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6818 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
6819 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
6820 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6822 levels = IDirect3DTexture9_GetLevelCount(texture);
6823 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6825 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
6827 surface = NULL;
6828 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
6829 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6830 if (surface)
6831 IDirect3DSurface9_Release(surface);
6833 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
6834 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6836 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
6837 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6838 if (SUCCEEDED(hr))
6840 hr = IDirect3DTexture9_UnlockRect(texture, i);
6841 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
6844 IDirect3DTexture9_Release(texture);
6846 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
6847 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6848 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6849 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
6850 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6851 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6853 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
6854 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6855 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6856 levels = IDirect3DTexture9_GetLevelCount(texture);
6857 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6858 IDirect3DTexture9_Release(texture);
6860 refcount = IDirect3DDevice9_Release(device);
6861 ok(!refcount, "Device has %u references left.\n", refcount);
6862 IDirect3D9_Release(d3d);
6863 DestroyWindow(window);
6866 static void test_filter(void)
6868 static const struct
6870 DWORD magfilter, minfilter, mipfilter;
6871 BOOL has_texture;
6872 HRESULT result;
6874 tests[] =
6876 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6877 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6878 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6879 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
6880 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
6882 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6883 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6884 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
6885 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
6887 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6888 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6889 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
6890 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
6891 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
6893 IDirect3DTexture9 *texture;
6894 IDirect3DDevice9 *device;
6895 IDirect3D9 *d3d;
6896 unsigned int i;
6897 ULONG refcount;
6898 DWORD passes;
6899 HWND window;
6900 HRESULT hr;
6902 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6903 ok(!!d3d, "Failed to create a D3D object.\n");
6905 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6906 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6908 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
6909 IDirect3D9_Release(d3d);
6910 return;
6913 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6914 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6916 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
6917 IDirect3D9_Release(d3d);
6918 return;
6921 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6922 0, 0, 640, 480, 0, 0, 0, 0);
6923 if (!(device = create_device(d3d, window, NULL)))
6925 skip("Failed to create a D3D device, skipping tests.\n");
6926 IDirect3D9_Release(d3d);
6927 DestroyWindow(window);
6928 return;
6931 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
6932 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
6933 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6935 /* Needed for ValidateDevice(). */
6936 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6937 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6939 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
6941 if (tests[i].has_texture)
6943 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
6944 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6946 else
6948 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6949 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6952 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
6953 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6954 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
6955 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6956 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
6957 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6959 passes = 0xdeadbeef;
6960 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
6961 ok(hr == tests[i].result,
6962 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
6963 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
6964 tests[i].mipfilter, tests[i].has_texture);
6965 if (SUCCEEDED(hr))
6966 ok(!!passes, "Got unexpected passes %#x.\n", passes);
6967 else
6968 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
6971 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6972 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6973 IDirect3DTexture9_Release(texture);
6975 refcount = IDirect3DDevice9_Release(device);
6976 ok(!refcount, "Device has %u references left.\n", refcount);
6977 IDirect3D9_Release(d3d);
6978 DestroyWindow(window);
6981 static void test_get_set_texture(void)
6983 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
6984 IDirect3DBaseTexture9 *texture;
6985 IDirect3DDevice9 *device;
6986 IDirect3D9 *d3d;
6987 ULONG refcount;
6988 HWND window;
6989 HRESULT hr;
6991 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6992 0, 0, 640, 480, 0, 0, 0, 0);
6993 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6994 ok(!!d3d, "Failed to create a D3D object.\n");
6995 if (!(device = create_device(d3d, window, NULL)))
6997 skip("Failed to create a D3D device, skipping tests.\n");
6998 IDirect3D9_Release(d3d);
6999 DestroyWindow(window);
7000 return;
7003 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
7004 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7005 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7006 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
7007 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7008 ok(!texture, "Got unexpected texture %p.\n", texture);
7010 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
7011 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
7012 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7013 texture_vtbl = texture->lpVtbl;
7014 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
7015 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7016 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7017 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7018 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7019 texture->lpVtbl = NULL;
7020 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7021 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7022 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7023 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7024 texture->lpVtbl = texture_vtbl;
7025 IDirect3DBaseTexture9_Release(texture);
7027 refcount = IDirect3DDevice9_Release(device);
7028 ok(!refcount, "Device has %u references left.\n", refcount);
7029 IDirect3D9_Release(d3d);
7030 DestroyWindow(window);
7033 static void test_lod(void)
7035 IDirect3DTexture9 *texture;
7036 IDirect3DDevice9 *device;
7037 IDirect3D9 *d3d;
7038 ULONG refcount;
7039 HWND window;
7040 HRESULT hr;
7041 DWORD ret;
7043 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7044 0, 0, 640, 480, 0, 0, 0, 0);
7045 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7046 ok(!!d3d, "Failed to create a D3D object.\n");
7047 if (!(device = create_device(d3d, window, NULL)))
7049 skip("Failed to create a D3D device, skipping tests.\n");
7050 IDirect3D9_Release(d3d);
7051 DestroyWindow(window);
7052 return;
7055 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
7056 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7057 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7059 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
7060 * return a HRESULT, so it can't return a normal error. Instead, the call
7061 * is simply ignored. */
7062 ret = IDirect3DTexture9_SetLOD(texture, 0);
7063 ok(!ret, "Got unexpected ret %u.\n", ret);
7064 ret = IDirect3DTexture9_SetLOD(texture, 1);
7065 ok(!ret, "Got unexpected ret %u.\n", ret);
7066 ret = IDirect3DTexture9_SetLOD(texture, 2);
7067 ok(!ret, "Got unexpected ret %u.\n", ret);
7068 ret = IDirect3DTexture9_GetLOD(texture);
7069 ok(!ret, "Got unexpected ret %u.\n", ret);
7071 IDirect3DTexture9_Release(texture);
7072 refcount = IDirect3DDevice9_Release(device);
7073 ok(!refcount, "Device has %u references left.\n", refcount);
7074 IDirect3D9_Release(d3d);
7075 DestroyWindow(window);
7078 static void test_surface_get_container(void)
7080 IDirect3DTexture9 *texture = NULL;
7081 IDirect3DSurface9 *surface = NULL;
7082 IDirect3DDevice9 *device;
7083 IUnknown *container;
7084 IDirect3D9 *d3d;
7085 ULONG refcount;
7086 HWND window;
7087 HRESULT hr;
7089 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7090 0, 0, 640, 480, 0, 0, 0, 0);
7091 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7092 ok(!!d3d, "Failed to create a D3D object.\n");
7093 if (!(device = create_device(d3d, window, NULL)))
7095 skip("Failed to create a D3D device, skipping tests.\n");
7096 IDirect3D9_Release(d3d);
7097 DestroyWindow(window);
7098 return;
7101 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
7102 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7103 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7104 ok(!!texture, "Got unexpected texture %p.\n", texture);
7106 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7107 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7108 ok(!!surface, "Got unexpected surface %p.\n", surface);
7110 /* These should work... */
7111 container = NULL;
7112 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
7113 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7114 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7115 IUnknown_Release(container);
7117 container = NULL;
7118 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
7119 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7120 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7121 IUnknown_Release(container);
7123 container = NULL;
7124 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
7125 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7126 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7127 IUnknown_Release(container);
7129 container = NULL;
7130 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
7131 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7132 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7133 IUnknown_Release(container);
7135 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
7136 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
7137 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7138 ok(!container, "Got unexpected container %p.\n", container);
7140 IDirect3DSurface9_Release(surface);
7141 IDirect3DTexture9_Release(texture);
7142 refcount = IDirect3DDevice9_Release(device);
7143 ok(!refcount, "Device has %u references left.\n", refcount);
7144 IDirect3D9_Release(d3d);
7145 DestroyWindow(window);
7148 static void test_surface_alignment(void)
7150 IDirect3DSurface9 *surface;
7151 IDirect3DDevice9 *device;
7152 D3DLOCKED_RECT lr;
7153 unsigned int i, j;
7154 IDirect3D9 *d3d;
7155 ULONG refcount;
7156 HWND window;
7157 HRESULT hr;
7159 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7160 0, 0, 640, 480, 0, 0, 0, 0);
7161 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7162 ok(!!d3d, "Failed to create a D3D object.\n");
7163 if (!(device = create_device(d3d, window, NULL)))
7165 skip("Failed to create a D3D device, skipping tests.\n");
7166 IDirect3D9_Release(d3d);
7167 DestroyWindow(window);
7168 return;
7171 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7172 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7173 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7174 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7176 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7177 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7178 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7179 /* Some applications also depend on the exact pitch, rather than just the
7180 * alignment. */
7181 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7182 hr = IDirect3DSurface9_UnlockRect(surface);
7183 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7184 IDirect3DSurface9_Release(surface);
7186 for (i = 0; i < 5; ++i)
7188 IDirect3DTexture9 *texture;
7189 unsigned int level_count;
7190 D3DSURFACE_DESC desc;
7191 int expected_pitch;
7193 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7194 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7195 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7196 if (FAILED(hr))
7198 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7199 continue;
7202 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7203 for (j = 0; j < level_count; ++j)
7205 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7206 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7207 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7208 hr = IDirect3DTexture9_UnlockRect(texture, j);
7209 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7211 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7212 if (i > 0)
7213 expected_pitch <<= 1;
7214 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7215 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7217 IDirect3DTexture9_Release(texture);
7220 refcount = IDirect3DDevice9_Release(device);
7221 ok(!refcount, "Device has %u references left.\n", refcount);
7222 IDirect3D9_Release(d3d);
7223 DestroyWindow(window);
7226 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7227 * different from regular formats. This test verifies we return the correct
7228 * memory offsets. */
7229 static void test_lockrect_offset(void)
7231 static const struct
7233 D3DFORMAT format;
7234 const char *name;
7235 unsigned int block_width;
7236 unsigned int block_height;
7237 unsigned int block_size;
7239 dxt_formats[] =
7241 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7242 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7243 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7244 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7245 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7246 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7247 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7249 unsigned int expected_offset, offset, i;
7250 const RECT rect = {60, 60, 68, 68};
7251 IDirect3DSurface9 *surface;
7252 D3DLOCKED_RECT locked_rect;
7253 IDirect3DDevice9 *device;
7254 int expected_pitch;
7255 IDirect3D9 *d3d;
7256 ULONG refcount;
7257 HWND window;
7258 BYTE *base;
7259 HRESULT hr;
7261 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7262 0, 0, 640, 480, 0, 0, 0, 0);
7263 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7264 ok(!!d3d, "Failed to create a D3D object.\n");
7265 if (!(device = create_device(d3d, window, NULL)))
7267 skip("Failed to create a D3D device, skipping tests.\n");
7268 IDirect3D9_Release(d3d);
7269 DestroyWindow(window);
7270 return;
7273 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
7275 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7276 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7278 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7279 continue;
7282 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7283 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7284 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7286 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7287 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7289 base = locked_rect.pBits;
7290 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7291 * dxt_formats[i].block_size;
7292 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7293 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7295 hr = IDirect3DSurface9_UnlockRect(surface);
7296 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7298 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7299 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7301 offset = (BYTE *)locked_rect.pBits - base;
7302 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7303 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7304 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7305 offset, dxt_formats[i].name, expected_offset);
7307 hr = IDirect3DSurface9_UnlockRect(surface);
7308 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7310 IDirect3DSurface9_Release(surface);
7313 refcount = IDirect3DDevice9_Release(device);
7314 ok(!refcount, "Device has %u references left.\n", refcount);
7315 IDirect3D9_Release(d3d);
7316 DestroyWindow(window);
7319 static void test_lockrect_invalid(void)
7321 static const struct
7323 RECT rect;
7324 HRESULT win7_result;
7326 test_data[] =
7328 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7329 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7330 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7331 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7332 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7333 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7334 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7335 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7336 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7337 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7338 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7339 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7340 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7342 static const RECT test_rect_2 = {0, 0, 8, 8};
7343 IDirect3DSurface9 *surface = NULL;
7344 D3DLOCKED_RECT locked_rect;
7345 IDirect3DDevice9 *device;
7346 IDirect3DTexture9 *texture;
7347 IDirect3DCubeTexture9 *cube_texture;
7348 HRESULT hr, expected_hr;
7349 unsigned int i, r;
7350 IDirect3D9 *d3d;
7351 ULONG refcount;
7352 HWND window;
7353 BYTE *base;
7354 static const struct
7356 D3DRESOURCETYPE type;
7357 D3DPOOL pool;
7358 const char *name;
7360 resources[] =
7362 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7363 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7364 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7365 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7366 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7367 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7368 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7371 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7372 0, 0, 640, 480, 0, 0, 0, 0);
7373 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7374 ok(!!d3d, "Failed to create a D3D object.\n");
7375 if (!(device = create_device(d3d, window, NULL)))
7377 skip("Failed to create a D3D device, skipping tests.\n");
7378 IDirect3D9_Release(d3d);
7379 DestroyWindow(window);
7380 return;
7383 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
7385 texture = NULL;
7386 cube_texture = NULL;
7387 switch (resources[r].type)
7389 case D3DRTYPE_SURFACE:
7390 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7391 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7392 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7393 hr, resources[r].name);
7394 break;
7396 case D3DRTYPE_TEXTURE:
7397 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7398 resources[r].pool, &texture, NULL);
7399 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7400 hr, resources[r].name);
7401 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7402 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7403 hr, resources[r].name);
7404 break;
7406 case D3DRTYPE_CUBETEXTURE:
7407 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7408 resources[r].pool, &cube_texture, NULL);
7409 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7410 hr, resources[r].name);
7411 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7412 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7413 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7414 hr, resources[r].name);
7415 break;
7417 default:
7418 break;
7421 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7422 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7423 base = locked_rect.pBits;
7424 hr = IDirect3DSurface9_UnlockRect(surface);
7425 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7426 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
7427 hr = IDirect3DSurface9_UnlockRect(surface);
7428 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
7430 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7432 unsigned int offset, expected_offset;
7433 const RECT *rect = &test_data[i].rect;
7435 locked_rect.pBits = (BYTE *)0xdeadbeef;
7436 locked_rect.Pitch = 0xdeadbeef;
7438 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7439 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7440 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7441 * one broken. */
7442 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7443 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7444 wine_dbgstr_rect(rect), hr, resources[r].name);
7445 if (FAILED(hr))
7446 continue;
7448 offset = (BYTE *)locked_rect.pBits - base;
7449 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7450 ok(offset == expected_offset,
7451 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7452 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7454 hr = IDirect3DSurface9_UnlockRect(surface);
7455 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7457 if (texture)
7459 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7460 ok(SUCCEEDED(hr),
7461 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7462 wine_dbgstr_rect(rect), hr, resources[r].name);
7463 if (FAILED(hr))
7464 continue;
7466 offset = (BYTE *)locked_rect.pBits - base;
7467 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7468 ok(offset == expected_offset,
7469 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7470 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7472 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7473 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7475 if (cube_texture)
7477 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7478 &locked_rect, rect, 0);
7479 ok(SUCCEEDED(hr),
7480 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7481 wine_dbgstr_rect(rect), hr, resources[r].name);
7482 if (FAILED(hr))
7483 continue;
7485 offset = (BYTE *)locked_rect.pBits - base;
7486 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7487 ok(offset == expected_offset,
7488 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7489 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7491 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7492 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7496 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7497 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7498 locked_rect.pBits = (BYTE *)0xdeadbeef;
7499 locked_rect.Pitch = 1;
7500 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7501 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7502 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7503 locked_rect.pBits, resources[r].name);
7504 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7505 locked_rect.Pitch, resources[r].name);
7506 hr = IDirect3DSurface9_UnlockRect(surface);
7507 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7509 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7510 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7511 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7512 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7513 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7514 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7515 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7516 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7517 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7518 hr = IDirect3DSurface9_UnlockRect(surface);
7519 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7521 IDirect3DSurface9_Release(surface);
7523 if (texture)
7525 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7526 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7527 hr, resources[r].name);
7528 locked_rect.pBits = (BYTE *)0xdeadbeef;
7529 locked_rect.Pitch = 1;
7530 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7531 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7532 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7533 locked_rect.pBits, resources[r].name);
7534 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7535 locked_rect.Pitch, resources[r].name);
7536 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7537 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7538 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7539 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7540 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7541 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7543 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7544 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7545 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7546 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7547 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7548 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7549 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7550 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7551 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7552 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7553 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7555 IDirect3DTexture9_Release(texture);
7557 if (cube_texture)
7559 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7560 &locked_rect, NULL, 0);
7561 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7562 hr, resources[r].name);
7563 locked_rect.pBits = (BYTE *)0xdeadbeef;
7564 locked_rect.Pitch = 1;
7565 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7566 &locked_rect, NULL, 0);
7567 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7568 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7569 locked_rect.pBits, resources[r].name);
7570 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7571 locked_rect.Pitch, resources[r].name);
7572 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7573 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7574 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7575 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7576 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7577 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7579 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7580 &locked_rect, &test_data[0].rect, 0);
7581 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7582 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7583 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7584 &locked_rect, &test_data[0].rect, 0);
7585 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7586 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7587 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7588 &locked_rect, &test_rect_2, 0);
7589 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7590 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7591 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7592 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7594 IDirect3DCubeTexture9_Release(cube_texture);
7598 refcount = IDirect3DDevice9_Release(device);
7599 ok(!refcount, "Device has %u references left.\n", refcount);
7600 IDirect3D9_Release(d3d);
7601 DestroyWindow(window);
7604 static void test_private_data(void)
7606 ULONG refcount, expected_refcount;
7607 IDirect3DTexture9 *texture;
7608 IDirect3DSurface9 *surface, *surface2;
7609 IDirect3DDevice9 *device;
7610 IDirect3D9 *d3d;
7611 IUnknown *ptr;
7612 HWND window;
7613 HRESULT hr;
7614 DWORD size;
7615 DWORD data[4] = {1, 2, 3, 4};
7616 static const GUID d3d9_private_data_test_guid2 =
7618 0x2e5afac2,
7619 0x87b5,
7620 0x4c10,
7621 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7624 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7625 0, 0, 640, 480, 0, 0, 0, 0);
7626 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7627 ok(!!d3d, "Failed to create a D3D object.\n");
7628 if (!(device = create_device(d3d, window, NULL)))
7630 skip("Failed to create a D3D device, skipping tests.\n");
7631 IDirect3D9_Release(d3d);
7632 DestroyWindow(window);
7633 return;
7636 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7637 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7638 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7640 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7641 device, 0, D3DSPD_IUNKNOWN);
7642 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7643 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7644 device, 5, D3DSPD_IUNKNOWN);
7645 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7646 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7647 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7648 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7650 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7651 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7652 sizeof(device), D3DSPD_IUNKNOWN);
7653 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7654 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7655 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7656 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7657 size = sizeof(ptr);
7658 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7659 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7660 IUnknown_Release(ptr);
7661 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7662 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7664 refcount = get_refcount((IUnknown *)device);
7665 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7666 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7667 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7668 expected_refcount = refcount + 1;
7669 refcount = get_refcount((IUnknown *)device);
7670 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7671 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7672 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7673 expected_refcount = refcount - 1;
7674 refcount = get_refcount((IUnknown *)device);
7675 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7677 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7678 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7679 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7680 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7681 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7682 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7683 refcount = get_refcount((IUnknown *)device);
7684 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7686 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7687 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7688 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7689 size = 2 * sizeof(ptr);
7690 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7691 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7692 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7693 expected_refcount = refcount + 2;
7694 refcount = get_refcount((IUnknown *)device);
7695 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7696 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
7697 IUnknown_Release(ptr);
7698 expected_refcount--;
7700 ptr = (IUnknown *)0xdeadbeef;
7701 size = 1;
7702 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7703 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7704 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7705 size = 2 * sizeof(ptr);
7706 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7707 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7708 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7709 refcount = get_refcount((IUnknown *)device);
7710 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7711 size = 1;
7712 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7713 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7714 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7715 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7716 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
7717 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7718 size = 0xdeadbabe;
7719 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
7720 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7721 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7722 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7723 /* GetPrivateData with size = NULL causes an access violation on Windows if the
7724 * requested data exists. */
7726 /* Destroying the surface frees the held reference. */
7727 IDirect3DSurface9_Release(surface);
7728 expected_refcount = refcount - 2;
7729 refcount = get_refcount((IUnknown *)device);
7730 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7732 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
7733 &texture, NULL);
7734 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7735 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7736 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
7737 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
7738 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
7740 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7741 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7743 memset(data, 0, sizeof(data));
7744 size = sizeof(data);
7745 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
7746 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7747 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
7748 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7749 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
7750 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
7752 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
7753 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7755 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7756 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7757 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
7758 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7760 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7761 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7763 IDirect3DSurface9_Release(surface2);
7764 IDirect3DSurface9_Release(surface);
7765 IDirect3DTexture9_Release(texture);
7767 refcount = IDirect3DDevice9_Release(device);
7768 ok(!refcount, "Device has %u references left.\n", refcount);
7769 IDirect3D9_Release(d3d);
7770 DestroyWindow(window);
7773 static void test_getdc(void)
7775 static const struct
7777 const char *name;
7778 D3DFORMAT format;
7779 unsigned int bit_count;
7780 DWORD mask_r, mask_g, mask_b;
7781 BOOL getdc_supported;
7783 testdata[] =
7785 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7786 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7787 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
7788 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7789 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7790 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
7791 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7792 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7793 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7794 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7795 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7796 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7797 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7798 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7799 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7800 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
7801 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7802 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7803 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7804 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7806 IDirect3DSurface9 *surface, *surface2;
7807 IDirect3DCubeTexture9 *cube_texture;
7808 IDirect3DTexture9 *texture;
7809 IDirect3DDevice9 *device;
7810 D3DLOCKED_RECT map_desc;
7811 IDirect3D9 *d3d;
7812 unsigned int i;
7813 ULONG refcount;
7814 HWND window;
7815 HDC dc, dc2;
7816 HRESULT hr;
7818 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7819 0, 0, 640, 480, 0, 0, 0, 0);
7820 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7821 ok(!!d3d, "Failed to create a D3D object.\n");
7822 if (!(device = create_device(d3d, window, NULL)))
7824 skip("Failed to create a D3D device, skipping tests.\n");
7825 IDirect3D9_Release(d3d);
7826 DestroyWindow(window);
7827 return;
7830 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
7832 texture = NULL;
7833 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7834 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
7835 if (FAILED(hr))
7837 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
7838 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
7839 if (FAILED(hr))
7841 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7842 continue;
7844 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7845 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7848 dc = (void *)0x1234;
7849 hr = IDirect3DSurface9_GetDC(surface, &dc);
7850 if (testdata[i].getdc_supported)
7851 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7852 else
7853 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7855 if (SUCCEEDED(hr))
7857 unsigned int width_bytes;
7858 DIBSECTION dib;
7859 HBITMAP bitmap;
7860 DWORD type;
7861 int size;
7863 type = GetObjectType(dc);
7864 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7865 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7866 type = GetObjectType(bitmap);
7867 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7869 size = GetObjectA(bitmap, sizeof(dib), &dib);
7870 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
7871 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
7872 dib.dsBm.bmType, testdata[i].name);
7873 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
7874 dib.dsBm.bmWidth, testdata[i].name);
7875 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
7876 dib.dsBm.bmHeight, testdata[i].name);
7877 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
7878 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
7879 dib.dsBm.bmWidthBytes, testdata[i].name);
7880 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
7881 dib.dsBm.bmPlanes, testdata[i].name);
7882 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
7883 "Got unexpected bit count %d for format %s.\n",
7884 dib.dsBm.bmBitsPixel, testdata[i].name);
7885 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
7886 dib.dsBm.bmBits, testdata[i].name);
7888 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
7889 dib.dsBmih.biSize, testdata[i].name);
7890 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
7891 dib.dsBmih.biHeight, testdata[i].name);
7892 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
7893 dib.dsBmih.biHeight, testdata[i].name);
7894 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
7895 dib.dsBmih.biPlanes, testdata[i].name);
7896 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
7897 dib.dsBmih.biBitCount, testdata[i].name);
7898 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
7899 "Got unexpected compression %#x for format %s.\n",
7900 dib.dsBmih.biCompression, testdata[i].name);
7901 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
7902 dib.dsBmih.biSizeImage, testdata[i].name);
7903 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
7904 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
7905 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
7906 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
7907 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
7908 dib.dsBmih.biClrUsed, testdata[i].name);
7909 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
7910 dib.dsBmih.biClrImportant, testdata[i].name);
7912 if (dib.dsBmih.biCompression == BI_BITFIELDS)
7914 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
7915 && dib.dsBitfields[2] == testdata[i].mask_b,
7916 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7917 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7919 else
7921 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
7922 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7923 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7925 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
7926 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
7928 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7929 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
7931 else
7933 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
7936 IDirect3DSurface9_Release(surface);
7937 if (texture)
7938 IDirect3DTexture9_Release(texture);
7940 if (!testdata[i].getdc_supported)
7941 continue;
7943 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
7944 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
7946 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7947 continue;
7950 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
7951 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7952 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
7953 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7955 hr = IDirect3DSurface9_GetDC(surface, &dc);
7956 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7957 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7958 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7959 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7960 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7961 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7962 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7964 hr = IDirect3DSurface9_GetDC(surface, &dc);
7965 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7966 dc2 = (void *)0x1234;
7967 hr = IDirect3DSurface9_GetDC(surface, &dc2);
7968 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7969 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
7970 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7971 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7972 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7973 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7975 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7976 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7977 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7978 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7979 hr = IDirect3DSurface9_UnlockRect(surface);
7980 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7981 hr = IDirect3DSurface9_UnlockRect(surface);
7982 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7984 hr = IDirect3DSurface9_GetDC(surface, &dc);
7985 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7986 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7987 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7988 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7989 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7991 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7992 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7993 hr = IDirect3DSurface9_GetDC(surface, &dc);
7994 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7995 hr = IDirect3DSurface9_UnlockRect(surface);
7996 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7998 hr = IDirect3DSurface9_GetDC(surface, &dc);
7999 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8000 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
8001 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8002 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
8003 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8004 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8005 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8007 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8008 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8009 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8010 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8011 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
8012 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8013 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8014 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8016 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8017 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8018 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8019 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8020 hr = IDirect3DSurface9_UnlockRect(surface2);
8021 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8022 hr = IDirect3DSurface9_UnlockRect(surface);
8023 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8025 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8026 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8027 hr = IDirect3DSurface9_GetDC(surface, &dc);
8028 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8029 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8030 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8031 hr = IDirect3DSurface9_UnlockRect(surface);
8032 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8034 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8035 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8036 hr = IDirect3DSurface9_GetDC(surface, &dc);
8037 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8038 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8039 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8040 hr = IDirect3DSurface9_UnlockRect(surface2);
8041 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8043 hr = IDirect3DSurface9_GetDC(surface, &dc);
8044 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8045 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8046 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8047 hr = IDirect3DSurface9_UnlockRect(surface2);
8048 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8049 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8050 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8052 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8053 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8054 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8055 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8056 hr = IDirect3DSurface9_UnlockRect(surface);
8057 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8058 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8059 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8061 hr = IDirect3DSurface9_UnlockRect(surface);
8062 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8063 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8064 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8065 hr = IDirect3DSurface9_UnlockRect(surface);
8066 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8067 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8068 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8069 hr = IDirect3DSurface9_UnlockRect(surface);
8070 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8072 hr = IDirect3DSurface9_UnlockRect(surface2);
8073 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8074 hr = IDirect3DSurface9_GetDC(surface, &dc);
8075 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8076 hr = IDirect3DSurface9_UnlockRect(surface2);
8077 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8078 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8079 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8080 hr = IDirect3DSurface9_UnlockRect(surface2);
8081 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8083 IDirect3DSurface9_Release(surface2);
8084 IDirect3DSurface9_Release(surface);
8085 IDirect3DCubeTexture9_Release(cube_texture);
8088 refcount = IDirect3DDevice9_Release(device);
8089 ok(!refcount, "Device has %u references left.\n", refcount);
8090 IDirect3D9_Release(d3d);
8091 DestroyWindow(window);
8094 static void test_surface_dimensions(void)
8096 IDirect3DSurface9 *surface;
8097 IDirect3DDevice9 *device;
8098 IDirect3D9 *d3d;
8099 ULONG refcount;
8100 HWND window;
8101 HRESULT hr;
8103 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8104 0, 0, 640, 480, 0, 0, 0, 0);
8105 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8106 ok(!!d3d, "Failed to create a D3D object.\n");
8107 if (!(device = create_device(d3d, window, NULL)))
8109 skip("Failed to create a D3D device, skipping tests.\n");
8110 IDirect3D9_Release(d3d);
8111 DestroyWindow(window);
8112 return;
8115 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8116 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8117 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8118 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8119 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8120 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8122 refcount = IDirect3DDevice9_Release(device);
8123 ok(!refcount, "Device has %u references left.\n", refcount);
8124 IDirect3D9_Release(d3d);
8125 DestroyWindow(window);
8128 static void test_surface_format_null(void)
8130 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8131 IDirect3DTexture9 *texture;
8132 IDirect3DSurface9 *surface;
8133 IDirect3DSurface9 *rt, *ds;
8134 D3DLOCKED_RECT locked_rect;
8135 IDirect3DDevice9 *device;
8136 D3DSURFACE_DESC desc;
8137 IDirect3D9 *d3d;
8138 ULONG refcount;
8139 HWND window;
8140 HRESULT hr;
8142 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8143 ok(!!d3d, "Failed to create a D3D object.\n");
8145 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8146 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8147 if (hr != D3D_OK)
8149 skip("No D3DFMT_NULL support, skipping test.\n");
8150 IDirect3D9_Release(d3d);
8151 return;
8154 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8155 0, 0, 640, 480, 0, 0, 0, 0);
8156 if (!(device = create_device(d3d, window, NULL)))
8158 skip("Failed to create a D3D device, skipping tests.\n");
8159 IDirect3D9_Release(d3d);
8160 DestroyWindow(window);
8161 return;
8164 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8165 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8166 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8168 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8169 D3DFMT_NULL, D3DFMT_D24S8);
8170 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8172 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8173 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8174 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8176 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8177 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8179 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8180 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8182 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8183 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8185 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8186 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8188 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8189 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8191 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8192 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8194 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8195 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8197 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8198 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8200 IDirect3DSurface9_Release(rt);
8201 IDirect3DSurface9_Release(ds);
8203 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8204 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8205 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8206 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8208 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8209 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8210 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8211 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8213 hr = IDirect3DSurface9_UnlockRect(surface);
8214 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8216 IDirect3DSurface9_Release(surface);
8218 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8219 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8220 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8221 IDirect3DTexture9_Release(texture);
8223 refcount = IDirect3DDevice9_Release(device);
8224 ok(!refcount, "Device has %u references left.\n", refcount);
8225 IDirect3D9_Release(d3d);
8226 DestroyWindow(window);
8229 static void test_surface_double_unlock(void)
8231 static const D3DPOOL pools[] =
8233 D3DPOOL_DEFAULT,
8234 D3DPOOL_SCRATCH,
8235 D3DPOOL_SYSTEMMEM,
8237 IDirect3DSurface9 *surface;
8238 IDirect3DDevice9 *device;
8239 D3DLOCKED_RECT lr;
8240 IDirect3D9 *d3d;
8241 unsigned int i;
8242 ULONG refcount;
8243 HWND window;
8244 HRESULT hr;
8246 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8247 0, 0, 640, 480, 0, 0, 0, 0);
8248 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8249 ok(!!d3d, "Failed to create a D3D object.\n");
8250 if (!(device = create_device(d3d, window, NULL)))
8252 skip("Failed to create a D3D device, skipping tests.\n");
8253 IDirect3D9_Release(d3d);
8254 DestroyWindow(window);
8255 return;
8258 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
8260 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8261 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8262 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8264 hr = IDirect3DSurface9_UnlockRect(surface);
8265 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8266 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8267 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8268 hr = IDirect3DSurface9_UnlockRect(surface);
8269 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8270 hr = IDirect3DSurface9_UnlockRect(surface);
8271 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8273 IDirect3DSurface9_Release(surface);
8276 refcount = IDirect3DDevice9_Release(device);
8277 ok(!refcount, "Device has %u references left.\n", refcount);
8278 IDirect3D9_Release(d3d);
8279 DestroyWindow(window);
8282 static void test_surface_blocks(void)
8284 static const struct
8286 D3DFORMAT fmt;
8287 const char *name;
8288 unsigned int block_width;
8289 unsigned int block_height;
8290 BOOL broken;
8291 BOOL create_size_checked, core_fmt;
8293 formats[] =
8295 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8296 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8297 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8298 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8299 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8300 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8301 * which doesn't match the format spec. On newer Nvidia cards
8302 * they have the correct 4x4 block size */
8303 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8304 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8305 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8306 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8308 static const struct
8310 D3DPOOL pool;
8311 const char *name;
8312 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8313 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8314 BOOL success;
8316 pools[] =
8318 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8319 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8320 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8321 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8323 static struct
8325 D3DRESOURCETYPE rtype;
8326 const char *type_name;
8327 D3DPOOL pool;
8328 const char *pool_name;
8329 BOOL need_driver_support, need_runtime_support;
8331 create_tests[] =
8333 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8334 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8335 /* Managed offscreen plain surfaces are not supported */
8336 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8338 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8339 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8340 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8341 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8343 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8344 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8345 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8346 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8348 IDirect3DTexture9 *texture;
8349 IDirect3DCubeTexture9 *cube_texture;
8350 IDirect3DSurface9 *surface;
8351 D3DLOCKED_RECT locked_rect;
8352 IDirect3DDevice9 *device;
8353 unsigned int i, j, k, w, h;
8354 BOOL surface_only;
8355 IDirect3D9 *d3d;
8356 ULONG refcount;
8357 HWND window;
8358 HRESULT hr;
8359 RECT rect;
8360 BOOL tex_pow2, cube_pow2;
8361 D3DCAPS9 caps;
8362 static const RECT invalid[] =
8364 {60, 60, 60, 68}, /* 0 height */
8365 {60, 60, 68, 60}, /* 0 width */
8366 {68, 60, 60, 68}, /* left > right */
8367 {60, 68, 68, 60}, /* top > bottom */
8368 {-8, 60, 0, 68}, /* left < surface */
8369 {60, -8, 68, 0}, /* top < surface */
8370 {-16, 60, -8, 68}, /* right < surface */
8371 {60, -16, 68, -8}, /* bottom < surface */
8372 {60, 60, 136, 68}, /* right > surface */
8373 {60, 60, 68, 136}, /* bottom > surface */
8374 {136, 60, 144, 68}, /* left > surface */
8375 {60, 136, 68, 144}, /* top > surface */
8378 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8379 0, 0, 640, 480, 0, 0, 0, 0);
8380 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8381 ok(!!d3d, "Failed to create a D3D object.\n");
8382 if (!(device = create_device(d3d, window, NULL)))
8384 skip("Failed to create a D3D device, skipping tests.\n");
8385 IDirect3D9_Release(d3d);
8386 DestroyWindow(window);
8387 return;
8390 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8391 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8392 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8393 if (tex_pow2)
8394 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8395 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8397 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
8399 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8401 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8402 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8403 tex_support = SUCCEEDED(hr);
8404 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8405 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8406 cube_support = SUCCEEDED(hr);
8407 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8408 0, D3DRTYPE_SURFACE, formats[i].fmt);
8409 surface_support = SUCCEEDED(hr);
8411 /* Scratch pool in general allows texture creation even if the driver does
8412 * not support the format. If the format is an extension format that is not
8413 * known to the runtime, like ATI2N, some driver support is required for
8414 * this to work.
8416 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8417 * about ATI2N. I cannot check this because all my Vista+ machines support
8418 * ATI2N in hardware, but none of my WinXP machines do. */
8419 format_known = tex_support || cube_support || surface_support;
8421 for (w = 1; w <= 8; w++)
8423 for (h = 1; h <= 8; h++)
8425 BOOL block_aligned = TRUE;
8426 BOOL size_is_pow2;
8428 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8429 block_aligned = FALSE;
8431 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8433 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
8435 BOOL support, pow2;
8436 HRESULT expect_hr;
8437 BOOL may_succeed = FALSE;
8438 IUnknown **check_null;
8440 if (!formats[i].core_fmt)
8442 /* AMD warns against creating ATI2N textures smaller than
8443 * the block size because the runtime cannot calculate the
8444 * correct texture size. Generalize this for all extension
8445 * formats. */
8446 if (w < formats[i].block_width || h < formats[i].block_height)
8447 continue;
8450 texture = (IDirect3DTexture9 *)0xdeadbeef;
8451 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8452 surface = (IDirect3DSurface9 *)0xdeadbeef;
8454 switch (create_tests[j].rtype)
8456 case D3DRTYPE_TEXTURE:
8457 check_null = (IUnknown **)&texture;
8458 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8459 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8460 support = tex_support;
8461 pow2 = tex_pow2;
8462 break;
8464 case D3DRTYPE_CUBETEXTURE:
8465 if (w != h)
8466 continue;
8467 check_null = (IUnknown **)&cube_texture;
8468 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8469 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8470 support = cube_support;
8471 pow2 = cube_pow2;
8472 break;
8474 case D3DRTYPE_SURFACE:
8475 check_null = (IUnknown **)&surface;
8476 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8477 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8478 support = surface_support;
8479 pow2 = FALSE;
8480 break;
8482 default:
8483 check_null = NULL;
8484 pow2 = FALSE;
8485 support = FALSE;
8486 break;
8489 if (create_tests[j].need_driver_support && !support)
8490 expect_hr = D3DERR_INVALIDCALL;
8491 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8492 expect_hr = D3DERR_INVALIDCALL;
8493 else if (formats[i].create_size_checked && !block_aligned)
8494 expect_hr = D3DERR_INVALIDCALL;
8495 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8496 expect_hr = D3DERR_INVALIDCALL;
8497 else
8498 expect_hr = D3D_OK;
8500 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8501 * does not support it. Accept scratch creation of extension formats on
8502 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8503 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8504 * support it. */
8505 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8506 may_succeed = TRUE;
8508 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8509 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8510 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8511 if (FAILED(hr))
8512 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8513 else
8514 IUnknown_Release(*check_null);
8519 surface_only = FALSE;
8520 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8521 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8522 dynamic_tex_support = SUCCEEDED(hr);
8523 if (!dynamic_tex_support)
8525 if (!surface_support)
8527 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8528 continue;
8530 surface_only = TRUE;
8533 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
8535 switch (pools[j].pool)
8537 case D3DPOOL_SYSTEMMEM:
8538 case D3DPOOL_MANAGED:
8539 if (surface_only)
8540 continue;
8541 /* Fall through */
8542 case D3DPOOL_DEFAULT:
8543 if (surface_only)
8545 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8546 formats[i].fmt, pools[j].pool, &surface, NULL);
8547 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8549 else
8551 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8552 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8553 formats[i].fmt, pools[j].pool, &texture, NULL);
8554 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8555 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8556 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8557 IDirect3DTexture9_Release(texture);
8559 break;
8561 case D3DPOOL_SCRATCH:
8562 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8563 formats[i].fmt, pools[j].pool, &surface, NULL);
8564 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8565 break;
8567 default:
8568 break;
8571 if (formats[i].block_width > 1)
8573 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8574 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8575 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8576 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8577 SUCCEEDED(hr) ? "succeeded" : "failed",
8578 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8579 if (SUCCEEDED(hr))
8581 hr = IDirect3DSurface9_UnlockRect(surface);
8582 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8585 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8586 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8587 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8588 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8589 SUCCEEDED(hr) ? "succeeded" : "failed",
8590 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8591 if (SUCCEEDED(hr))
8593 hr = IDirect3DSurface9_UnlockRect(surface);
8594 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8598 if (formats[i].block_height > 1)
8600 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
8601 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8602 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8603 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8604 SUCCEEDED(hr) ? "succeeded" : "failed",
8605 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8606 if (SUCCEEDED(hr))
8608 hr = IDirect3DSurface9_UnlockRect(surface);
8609 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8612 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
8613 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8614 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8615 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8616 SUCCEEDED(hr) ? "succeeded" : "failed",
8617 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8618 if (SUCCEEDED(hr))
8620 hr = IDirect3DSurface9_UnlockRect(surface);
8621 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8625 for (k = 0; k < sizeof(invalid) / sizeof(*invalid); ++k)
8627 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
8628 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
8629 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
8630 formats[i].name, pools[j].name, k);
8631 if (SUCCEEDED(hr))
8633 hr = IDirect3DSurface9_UnlockRect(surface);
8634 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8638 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8639 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8640 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
8641 hr = IDirect3DSurface9_UnlockRect(surface);
8642 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8644 IDirect3DSurface9_Release(surface);
8647 if (!dynamic_tex_support)
8649 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
8650 continue;
8653 if (formats[i].block_width == 1 && formats[i].block_height == 1)
8654 continue;
8655 if (!formats[i].core_fmt)
8656 continue;
8658 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
8659 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
8660 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
8662 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
8663 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8664 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8665 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8667 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
8668 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
8669 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8670 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8671 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8672 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8674 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8675 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8676 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8677 if (SUCCEEDED(hr))
8678 IDirect3DTexture9_UnlockRect(texture, 1);
8680 IDirect3DTexture9_Release(texture);
8683 refcount = IDirect3DDevice9_Release(device);
8684 ok(!refcount, "Device has %u references left.\n", refcount);
8685 IDirect3D9_Release(d3d);
8686 DestroyWindow(window);
8689 static void test_set_palette(void)
8691 IDirect3DDevice9 *device;
8692 IDirect3D9 *d3d9;
8693 UINT refcount;
8694 HWND window;
8695 HRESULT hr;
8696 PALETTEENTRY pal[256];
8697 unsigned int i;
8698 D3DCAPS9 caps;
8700 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8701 0, 0, 640, 480, 0, 0, 0, 0);
8702 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8703 ok(!!d3d9, "Failed to create a D3D object.\n");
8704 if (!(device = create_device(d3d9, window, NULL)))
8706 skip("Failed to create a D3D device, skipping tests.\n");
8707 DestroyWindow(window);
8708 return;
8711 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8713 pal[i].peRed = i;
8714 pal[i].peGreen = i;
8715 pal[i].peBlue = i;
8716 pal[i].peFlags = 0xff;
8718 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8719 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8721 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8722 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8723 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8725 pal[i].peRed = i;
8726 pal[i].peGreen = i;
8727 pal[i].peBlue = i;
8728 pal[i].peFlags = i;
8730 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
8732 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8733 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8735 else
8737 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8738 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
8741 refcount = IDirect3DDevice9_Release(device);
8742 ok(!refcount, "Device has %u references left.\n", refcount);
8743 IDirect3D9_Release(d3d9);
8744 DestroyWindow(window);
8747 static void test_swvp_buffer(void)
8749 IDirect3DDevice9 *device;
8750 IDirect3D9 *d3d9;
8751 UINT refcount;
8752 HWND window;
8753 HRESULT hr;
8754 unsigned int i;
8755 IDirect3DVertexBuffer9 *buffer;
8756 static const unsigned int bufsize = 1024;
8757 D3DVERTEXBUFFER_DESC desc;
8758 struct device_desc device_desc;
8759 struct
8761 float x, y, z;
8762 } *ptr, *ptr2;
8764 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8765 0, 0, 640, 480, 0, 0, 0, 0);
8766 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8767 ok(!!d3d9, "Failed to create a D3D object.\n");
8769 device_desc.device_window = window;
8770 device_desc.width = 640;
8771 device_desc.height = 480;
8772 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
8773 if (!(device = create_device(d3d9, window, &device_desc)))
8775 skip("Failed to create a D3D device, skipping tests.\n");
8776 DestroyWindow(window);
8777 IDirect3D9_Release(d3d9);
8778 return;
8781 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
8782 D3DPOOL_DEFAULT, &buffer, NULL);
8783 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8784 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8785 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8786 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
8787 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
8788 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
8790 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8791 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8792 for (i = 0; i < bufsize; i++)
8794 ptr[i].x = i * 1.0f;
8795 ptr[i].y = i * 2.0f;
8796 ptr[i].z = i * 3.0f;
8798 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8799 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8801 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8802 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8803 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8804 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8805 hr = IDirect3DDevice9_BeginScene(device);
8806 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8807 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8808 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8809 hr = IDirect3DDevice9_EndScene(device);
8810 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8812 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8813 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8814 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
8815 for (i = 0; i < bufsize; i++)
8817 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8819 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
8820 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8821 break;
8824 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8825 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8827 IDirect3DVertexBuffer9_Release(buffer);
8828 refcount = IDirect3DDevice9_Release(device);
8829 ok(!refcount, "Device has %u references left.\n", refcount);
8830 IDirect3D9_Release(d3d9);
8831 DestroyWindow(window);
8834 static void test_managed_buffer(void)
8836 static const unsigned int vertex_count = 1024;
8837 IDirect3DVertexBuffer9 *buffer;
8838 D3DVERTEXBUFFER_DESC desc;
8839 IDirect3DDevice9 *device;
8840 struct vec3 *ptr, *ptr2;
8841 IDirect3D9 *d3d9;
8842 unsigned int i;
8843 UINT refcount;
8844 HWND window;
8845 HRESULT hr;
8847 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8848 0, 0, 640, 480, 0, 0, 0, 0);
8849 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8850 ok(!!d3d9, "Failed to create a D3D object.\n");
8851 if (!(device = create_device(d3d9, window, NULL)))
8853 skip("Failed to create a D3D device, skipping tests.\n");
8854 IDirect3D9_Release(d3d9);
8855 DestroyWindow(window);
8856 return;
8859 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
8860 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
8861 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8862 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8863 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8864 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
8865 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
8867 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8868 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8869 for (i = 0; i < vertex_count; ++i)
8871 ptr[i].x = i * 1.0f;
8872 ptr[i].y = i * 2.0f;
8873 ptr[i].z = i * 3.0f;
8875 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8876 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8878 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8879 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8880 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8881 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8882 hr = IDirect3DDevice9_BeginScene(device);
8883 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8884 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8885 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8886 hr = IDirect3DDevice9_EndScene(device);
8887 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8889 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8890 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8891 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
8892 for (i = 0; i < vertex_count; ++i)
8894 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8896 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
8897 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8898 break;
8901 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8902 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8904 IDirect3DVertexBuffer9_Release(buffer);
8905 refcount = IDirect3DDevice9_Release(device);
8906 ok(!refcount, "Device has %u references left.\n", refcount);
8907 IDirect3D9_Release(d3d9);
8908 DestroyWindow(window);
8911 static void test_npot_textures(void)
8913 IDirect3DDevice9 *device = NULL;
8914 IDirect3D9 *d3d9;
8915 ULONG refcount;
8916 HWND window = NULL;
8917 HRESULT hr;
8918 D3DCAPS9 caps;
8919 IDirect3DTexture9 *texture;
8920 IDirect3DCubeTexture9 *cube_texture;
8921 IDirect3DVolumeTexture9 *volume_texture;
8922 struct
8924 D3DPOOL pool;
8925 const char *pool_name;
8926 HRESULT hr;
8928 pools[] =
8930 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
8931 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
8932 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
8933 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
8935 unsigned int i, levels;
8936 BOOL tex_pow2, cube_pow2, vol_pow2;
8938 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8939 0, 0, 640, 480, 0, 0, 0, 0);
8940 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8941 ok(!!d3d9, "Failed to create a D3D object.\n");
8942 if (!(device = create_device(d3d9, window, NULL)))
8944 skip("Failed to create a D3D device, skipping tests.\n");
8945 goto done;
8948 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8949 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8950 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8951 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8952 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8953 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
8954 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
8956 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
8958 for (levels = 0; levels <= 2; levels++)
8960 HRESULT expected;
8962 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
8963 pools[i].pool, &texture, NULL);
8964 if (!tex_pow2)
8966 expected = D3D_OK;
8968 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
8970 if (levels == 1)
8971 expected = D3D_OK;
8972 else
8973 expected = pools[i].hr;
8975 else
8977 expected = pools[i].hr;
8979 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
8980 pools[i].pool_name, levels, hr, expected);
8982 if (SUCCEEDED(hr))
8983 IDirect3DTexture9_Release(texture);
8986 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8987 &cube_texture, NULL);
8988 if (tex_pow2)
8990 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8991 pools[i].pool_name, hr, pools[i].hr);
8993 else
8995 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8996 pools[i].pool_name, hr, D3D_OK);
8999 if (SUCCEEDED(hr))
9000 IDirect3DCubeTexture9_Release(cube_texture);
9002 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9003 &volume_texture, NULL);
9004 if (tex_pow2)
9006 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9007 pools[i].pool_name, hr, pools[i].hr);
9009 else
9011 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9012 pools[i].pool_name, hr, D3D_OK);
9015 if (SUCCEEDED(hr))
9016 IDirect3DVolumeTexture9_Release(volume_texture);
9019 done:
9020 if (device)
9022 refcount = IDirect3DDevice9_Release(device);
9023 ok(!refcount, "Device has %u references left.\n", refcount);
9025 IDirect3D9_Release(d3d9);
9026 DestroyWindow(window);
9030 static void test_vidmem_accounting(void)
9032 IDirect3DDevice9 *device;
9033 IDirect3D9 *d3d9;
9034 ULONG refcount;
9035 HWND window;
9036 HRESULT hr = D3D_OK;
9037 IDirect3DTexture9 *textures[20];
9038 unsigned int i;
9039 UINT vidmem_start, vidmem_end, diff;
9041 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9042 0, 0, 640, 480, 0, 0, 0, 0);
9043 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9044 ok(!!d3d9, "Failed to create a D3D object.\n");
9045 if (!(device = create_device(d3d9, window, NULL)))
9047 skip("Failed to create a D3D device, skipping tests.\n");
9048 IDirect3D9_Release(d3d9);
9049 DestroyWindow(window);
9050 return;
9053 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
9054 memset(textures, 0, sizeof(textures));
9055 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
9057 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9058 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9059 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9060 * E_FAIL is returned on address space or system memory exhaustion */
9061 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9062 "Failed to create texture, hr %#x.\n", hr);
9064 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9066 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9067 diff = vidmem_start - vidmem_end;
9068 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9069 2 * i, diff / 1024 / 1024);
9071 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
9073 if (textures[i])
9074 IDirect3DTexture9_Release(textures[i]);
9077 refcount = IDirect3DDevice9_Release(device);
9078 ok(!refcount, "Device has %u references left.\n", refcount);
9079 IDirect3D9_Release(d3d9);
9080 DestroyWindow(window);
9083 static void test_volume_locking(void)
9085 IDirect3DDevice9 *device;
9086 IDirect3D9 *d3d9;
9087 HWND window;
9088 HRESULT hr;
9089 IDirect3DVolumeTexture9 *texture;
9090 unsigned int i;
9091 D3DLOCKED_BOX locked_box;
9092 ULONG refcount;
9093 D3DCAPS9 caps;
9094 static const struct
9096 D3DPOOL pool;
9097 DWORD usage;
9098 HRESULT create_hr, lock_hr;
9100 tests[] =
9102 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9103 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9104 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9105 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9106 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9107 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9108 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9109 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9112 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9113 0, 0, 640, 480, 0, 0, 0, 0);
9114 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9115 ok(!!d3d9, "Failed to create a D3D object.\n");
9116 if (!(device = create_device(d3d9, window, NULL)))
9118 skip("Failed to create a D3D device, skipping tests.\n");
9119 IDirect3D9_Release(d3d9);
9120 DestroyWindow(window);
9121 return;
9124 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9125 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9126 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9128 skip("Volume textures not supported, skipping test.\n");
9129 goto out;
9132 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9134 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9135 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9136 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9137 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9138 if (FAILED(hr))
9139 continue;
9141 locked_box.pBits = (void *)0xdeadbeef;
9142 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9143 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9144 if (SUCCEEDED(hr))
9146 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9147 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9149 else
9151 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9153 IDirect3DVolumeTexture9_Release(texture);
9156 out:
9157 refcount = IDirect3DDevice9_Release(device);
9158 ok(!refcount, "Device has %u references left.\n", refcount);
9159 IDirect3D9_Release(d3d9);
9160 DestroyWindow(window);
9163 static void test_update_volumetexture(void)
9165 IDirect3DDevice9 *device;
9166 IDirect3D9 *d3d9;
9167 HWND window;
9168 HRESULT hr;
9169 IDirect3DVolumeTexture9 *src, *dst;
9170 unsigned int i;
9171 D3DLOCKED_BOX locked_box;
9172 ULONG refcount;
9173 D3DCAPS9 caps;
9174 static const struct
9176 D3DPOOL src_pool, dst_pool;
9177 HRESULT hr;
9179 tests[] =
9181 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9182 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9183 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9184 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9186 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9187 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9188 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9189 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9191 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9192 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9193 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9194 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9196 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9197 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9198 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9199 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9201 static const struct
9203 UINT src_size, dst_size;
9204 UINT src_lvl, dst_lvl;
9205 D3DFORMAT src_fmt, dst_fmt;
9207 tests2[] =
9209 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9210 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9211 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9212 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9213 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9214 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9215 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9216 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9219 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9220 0, 0, 640, 480, 0, 0, 0, 0);
9221 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9222 ok(!!d3d9, "Failed to create a D3D object.\n");
9223 if (!(device = create_device(d3d9, window, NULL)))
9225 skip("Failed to create a D3D device, skipping tests.\n");
9226 IDirect3D9_Release(d3d9);
9227 DestroyWindow(window);
9228 return;
9231 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9232 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9233 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9235 skip("Volume textures not supported, skipping test.\n");
9236 goto out;
9239 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9241 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9242 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9244 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9245 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9246 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9247 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9248 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9249 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9251 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9252 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9253 *((DWORD *)locked_box.pBits) = 0x11223344;
9254 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9255 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9257 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9258 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9259 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9261 if (SUCCEEDED(hr))
9263 DWORD content = *((DWORD *)locked_box.pBits);
9264 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9265 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9266 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9267 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9268 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9270 IDirect3DVolumeTexture9_Release(src);
9271 IDirect3DVolumeTexture9_Release(dst);
9274 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9276 skip("Mipmapped volume maps not supported.\n");
9277 goto out;
9280 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
9282 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9283 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9284 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9285 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9286 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9287 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9288 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9289 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9291 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9292 todo_wine_if (FAILED(hr))
9293 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9295 IDirect3DVolumeTexture9_Release(src);
9296 IDirect3DVolumeTexture9_Release(dst);
9299 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9300 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9301 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9302 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9303 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9305 * I'm not adding tests for this behavior until an application needs it. */
9307 out:
9308 refcount = IDirect3DDevice9_Release(device);
9309 ok(!refcount, "Device has %u references left.\n", refcount);
9310 IDirect3D9_Release(d3d9);
9311 DestroyWindow(window);
9314 static void test_create_rt_ds_fail(void)
9316 IDirect3DDevice9 *device;
9317 HWND window;
9318 HRESULT hr;
9319 ULONG refcount;
9320 IDirect3D9 *d3d9;
9321 IDirect3DSurface9 *surface;
9323 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9324 0, 0, 640, 480, 0, 0, 0, 0);
9325 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9326 ok(!!d3d9, "Failed to create a D3D object.\n");
9327 if (!(device = create_device(d3d9, window, NULL)))
9329 skip("Failed to create a D3D device, skipping tests.\n");
9330 IDirect3D9_Release(d3d9);
9331 DestroyWindow(window);
9332 return;
9335 /* Output pointer == NULL segfaults on Windows. */
9337 surface = (IDirect3DSurface9 *)0xdeadbeef;
9338 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9339 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9340 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9341 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9342 if (SUCCEEDED(hr))
9343 IDirect3DSurface9_Release(surface);
9345 surface = (IDirect3DSurface9 *)0xdeadbeef;
9346 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9347 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9348 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9349 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9350 if (SUCCEEDED(hr))
9351 IDirect3DSurface9_Release(surface);
9353 refcount = IDirect3DDevice9_Release(device);
9354 ok(!refcount, "Device has %u references left.\n", refcount);
9355 IDirect3D9_Release(d3d9);
9356 DestroyWindow(window);
9359 static void test_volume_blocks(void)
9361 IDirect3DDevice9 *device;
9362 IDirect3D9 *d3d9;
9363 UINT refcount;
9364 HWND window;
9365 HRESULT hr;
9366 D3DCAPS9 caps;
9367 IDirect3DVolumeTexture9 *texture;
9368 unsigned int w, h, d, i, j;
9369 static const struct
9371 D3DFORMAT fmt;
9372 const char *name;
9373 unsigned int block_width;
9374 unsigned int block_height;
9375 unsigned int block_depth;
9376 unsigned int block_size;
9377 unsigned int broken;
9378 BOOL create_size_checked, core_fmt;
9380 formats[] =
9382 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9383 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9384 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9385 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9386 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9387 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9388 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9389 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9390 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9391 * which doesn't match the format spec. On newer Nvidia cards
9392 * it has the correct 4x4 block size.
9393 * ATI1N volume textures are only supported by AMD GPUs right
9394 * now and locking offsets seem just wrong. */
9395 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9396 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9397 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9398 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9400 static const struct
9402 D3DPOOL pool;
9403 const char *name;
9404 BOOL need_driver_support, need_runtime_support;
9406 create_tests[] =
9408 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9409 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9410 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9411 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9413 static const struct
9415 unsigned int x, y, z, x2, y2, z2;
9417 offset_tests[] =
9419 {0, 0, 0, 8, 8, 8},
9420 {0, 0, 3, 8, 8, 8},
9421 {0, 4, 0, 8, 8, 8},
9422 {0, 4, 3, 8, 8, 8},
9423 {4, 0, 0, 8, 8, 8},
9424 {4, 0, 3, 8, 8, 8},
9425 {4, 4, 0, 8, 8, 8},
9426 {4, 4, 3, 8, 8, 8},
9428 D3DBOX box;
9429 D3DLOCKED_BOX locked_box;
9430 BYTE *base;
9431 INT expected_row_pitch, expected_slice_pitch;
9432 BOOL support;
9433 BOOL pow2;
9434 unsigned int offset, expected_offset;
9436 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9437 0, 0, 640, 480, 0, 0, 0, 0);
9438 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9439 ok(!!d3d9, "Failed to create a D3D object.\n");
9440 if (!(device = create_device(d3d9, window, NULL)))
9442 skip("Failed to create a D3D device, skipping tests.\n");
9443 IDirect3D9_Release(d3d9);
9444 DestroyWindow(window);
9445 return;
9447 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9448 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9449 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9451 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
9453 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9454 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9455 support = SUCCEEDED(hr);
9457 /* Test creation restrictions */
9458 for (w = 1; w <= 8; w++)
9460 for (h = 1; h <= 8; h++)
9462 for (d = 1; d <= 8; d++)
9464 HRESULT expect_hr;
9465 BOOL size_is_pow2;
9466 BOOL block_aligned = TRUE;
9468 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9469 block_aligned = FALSE;
9471 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9473 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
9475 BOOL may_succeed = FALSE;
9477 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9478 expect_hr = D3DERR_INVALIDCALL;
9479 else if (formats[i].create_size_checked && !block_aligned)
9480 expect_hr = D3DERR_INVALIDCALL;
9481 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9482 expect_hr = D3DERR_INVALIDCALL;
9483 else if (create_tests[j].need_driver_support && !support)
9484 expect_hr = D3DERR_INVALIDCALL;
9485 else
9486 expect_hr = D3D_OK;
9488 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9489 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9490 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9492 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9493 * does not support it. Accept scratch creation of extension formats on
9494 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9495 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9496 * support it. */
9497 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9498 may_succeed = TRUE;
9500 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9501 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9502 hr, formats[i].name, create_tests[j].name, w, h, d);
9504 if (FAILED(hr))
9505 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9506 else
9507 IDirect3DVolumeTexture9_Release(texture);
9513 if (!support && !formats[i].core_fmt)
9514 continue;
9516 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9517 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9518 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9520 /* Test lockrect offset */
9521 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
9523 unsigned int bytes_per_pixel;
9524 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9526 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9527 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9529 base = locked_box.pBits;
9530 if (formats[i].broken == 1)
9532 expected_row_pitch = bytes_per_pixel * 24;
9534 else if (formats[i].broken == 2)
9536 expected_row_pitch = 24;
9538 else
9540 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9541 * formats[i].block_size;
9543 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9544 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9546 if (formats[i].broken)
9548 expected_slice_pitch = expected_row_pitch * 8;
9550 else
9552 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9553 * expected_row_pitch;
9555 ok(locked_box.SlicePitch == expected_slice_pitch,
9556 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9557 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9559 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9560 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9562 box.Left = offset_tests[j].x;
9563 box.Top = offset_tests[j].y;
9564 box.Front = offset_tests[j].z;
9565 box.Right = offset_tests[j].x2;
9566 box.Bottom = offset_tests[j].y2;
9567 box.Back = offset_tests[j].z2;
9568 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9569 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9571 offset = (BYTE *)locked_box.pBits - base;
9572 if (formats[i].broken == 1)
9574 expected_offset = box.Front * expected_slice_pitch
9575 + box.Top * expected_row_pitch
9576 + box.Left * bytes_per_pixel;
9578 else if (formats[i].broken == 2)
9580 expected_offset = box.Front * expected_slice_pitch
9581 + box.Top * expected_row_pitch
9582 + box.Left;
9584 else
9586 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9587 + (box.Top / formats[i].block_height) * expected_row_pitch
9588 + (box.Left / formats[i].block_width) * formats[i].block_size;
9590 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9591 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9593 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9594 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9597 /* Test partial block locks */
9598 box.Front = 0;
9599 box.Back = 1;
9600 if (formats[i].block_width > 1)
9602 box.Left = formats[i].block_width >> 1;
9603 box.Top = 0;
9604 box.Right = formats[i].block_width;
9605 box.Bottom = formats[i].block_height;
9606 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9607 ok(FAILED(hr) || broken(formats[i].broken),
9608 "Partial block lock succeeded, expected failure, format %s.\n",
9609 formats[i].name);
9610 if (SUCCEEDED(hr))
9612 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9613 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9616 box.Left = 0;
9617 box.Top = 0;
9618 box.Right = formats[i].block_width >> 1;
9619 box.Bottom = formats[i].block_height;
9620 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9621 ok(FAILED(hr) || broken(formats[i].broken),
9622 "Partial block lock succeeded, expected failure, format %s.\n",
9623 formats[i].name);
9624 if (SUCCEEDED(hr))
9626 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9627 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9631 if (formats[i].block_height > 1)
9633 box.Left = 0;
9634 box.Top = formats[i].block_height >> 1;
9635 box.Right = formats[i].block_width;
9636 box.Bottom = formats[i].block_height;
9637 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9638 ok(FAILED(hr) || broken(formats[i].broken),
9639 "Partial block lock succeeded, expected failure, format %s.\n",
9640 formats[i].name);
9641 if (SUCCEEDED(hr))
9643 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9644 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9647 box.Left = 0;
9648 box.Top = 0;
9649 box.Right = formats[i].block_width;
9650 box.Bottom = formats[i].block_height >> 1;
9651 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9652 ok(FAILED(hr) || broken(formats[i].broken),
9653 "Partial block lock succeeded, expected failure, format %s.\n",
9654 formats[i].name);
9655 if (SUCCEEDED(hr))
9657 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9658 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9662 /* Test full block lock */
9663 box.Left = 0;
9664 box.Top = 0;
9665 box.Right = formats[i].block_width;
9666 box.Bottom = formats[i].block_height;
9667 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9668 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9669 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9670 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9672 IDirect3DVolumeTexture9_Release(texture);
9674 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
9675 * does not allocate surfaces smaller than the blocksize properly. */
9676 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
9678 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
9679 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9680 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9682 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
9683 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9684 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9685 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9687 box.Left = box.Top = box.Front = 0;
9688 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
9689 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
9690 box.Back = 1;
9691 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9692 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9693 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9694 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9696 box.Right = formats[i].block_width;
9697 box.Bottom = formats[i].block_height;
9698 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9699 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9700 if (SUCCEEDED(hr))
9701 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9703 IDirect3DVolumeTexture9_Release(texture);
9707 refcount = IDirect3DDevice9_Release(device);
9708 ok(!refcount, "Device has %u references left.\n", refcount);
9709 IDirect3D9_Release(d3d9);
9710 DestroyWindow(window);
9713 static void test_lockbox_invalid(void)
9715 static const struct
9717 D3DBOX box;
9718 HRESULT result;
9720 test_data[] =
9722 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
9723 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
9724 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
9725 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
9726 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
9727 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
9728 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
9729 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
9730 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
9731 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
9732 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
9733 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
9734 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
9735 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
9737 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
9738 IDirect3DVolumeTexture9 *texture = NULL;
9739 D3DLOCKED_BOX locked_box;
9740 IDirect3DDevice9 *device;
9741 IDirect3D9 *d3d;
9742 unsigned int i;
9743 ULONG refcount;
9744 HWND window;
9745 BYTE *base;
9746 HRESULT hr;
9748 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9749 0, 0, 640, 480, 0, 0, 0, 0);
9750 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9751 ok(!!d3d, "Failed to create a D3D object.\n");
9752 if (!(device = create_device(d3d, window, NULL)))
9754 skip("Failed to create a D3D device, skipping tests.\n");
9755 IDirect3D9_Release(d3d);
9756 DestroyWindow(window);
9757 return;
9760 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
9761 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
9762 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9763 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9764 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9765 base = locked_box.pBits;
9766 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9767 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9769 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
9771 unsigned int offset, expected_offset;
9772 const D3DBOX *box = &test_data[i].box;
9774 locked_box.pBits = (BYTE *)0xdeadbeef;
9775 locked_box.RowPitch = 0xdeadbeef;
9776 locked_box.SlicePitch = 0xdeadbeef;
9778 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
9779 /* Unlike surfaces, volumes properly check the box even in Windows XP */
9780 ok(hr == test_data[i].result,
9781 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
9782 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
9783 test_data[i].result);
9784 if (FAILED(hr))
9785 continue;
9787 offset = (BYTE *)locked_box.pBits - base;
9788 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
9789 ok(offset == expected_offset,
9790 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
9791 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
9793 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9794 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9797 /* locked_box = NULL throws an exception on Windows */
9798 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9799 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9800 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9801 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9802 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9803 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9804 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9805 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9807 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9808 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9809 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9810 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9811 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9812 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9813 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9814 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9815 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
9816 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9817 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
9818 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
9819 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9820 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9822 IDirect3DVolumeTexture9_Release(texture);
9823 refcount = IDirect3DDevice9_Release(device);
9824 ok(!refcount, "Device has %u references left.\n", refcount);
9825 IDirect3D9_Release(d3d);
9826 DestroyWindow(window);
9829 static void test_shared_handle(void)
9831 IDirect3DDevice9 *device;
9832 IDirect3D9 *d3d;
9833 ULONG refcount;
9834 HWND window;
9835 HRESULT hr;
9836 /* Native d3d9ex refuses to create a shared texture if the texture pointer
9837 * is not initialized to NULL. Make sure this doesn't cause issues here. */
9838 IDirect3DTexture9 *texture = NULL;
9839 IDirect3DSurface9 *surface = NULL;
9840 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
9841 IDirect3DIndexBuffer9 *index_buffer = NULL;
9842 HANDLE handle = NULL;
9843 void *mem;
9844 D3DCAPS9 caps;
9846 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9847 0, 0, 640, 480, 0, 0, 0, 0);
9848 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9849 ok(!!d3d, "Failed to create a D3D object.\n");
9850 if (!(device = create_device(d3d, window, NULL)))
9852 skip("Failed to create a D3D device, skipping tests.\n");
9853 IDirect3D9_Release(d3d);
9854 DestroyWindow(window);
9855 return;
9858 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9859 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9860 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
9862 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
9863 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
9864 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9865 D3DPOOL_DEFAULT, &texture, &handle);
9866 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9867 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9868 D3DPOOL_SYSTEMMEM, &texture, &mem);
9869 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9871 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9872 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
9873 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9874 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9875 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
9876 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9878 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9879 &vertex_buffer, &handle);
9880 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9881 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9882 &vertex_buffer, &mem);
9883 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
9885 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9886 &index_buffer, &handle);
9887 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9888 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9889 &index_buffer, &mem);
9890 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9892 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9894 IDirect3DCubeTexture9 *cube_texture = NULL;
9895 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9896 D3DPOOL_DEFAULT, &cube_texture, &handle);
9897 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9898 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9899 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
9900 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9903 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
9905 IDirect3DVolumeTexture9 *volume_texture = NULL;
9906 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9907 D3DPOOL_DEFAULT, &volume_texture, &handle);
9908 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9909 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9910 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
9911 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9914 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
9915 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9916 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9918 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
9919 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9920 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9922 HeapFree(GetProcessHeap(), 0, mem);
9923 refcount = IDirect3DDevice9_Release(device);
9924 ok(!refcount, "Device has %u references left.\n", refcount);
9925 IDirect3D9_Release(d3d);
9926 DestroyWindow(window);
9929 static void test_pixel_format(void)
9931 HWND hwnd, hwnd2 = NULL;
9932 HDC hdc, hdc2 = NULL;
9933 HMODULE gl = NULL;
9934 int format, test_format;
9935 PIXELFORMATDESCRIPTOR pfd;
9936 IDirect3D9 *d3d9 = NULL;
9937 IDirect3DDevice9 *device = NULL;
9938 HRESULT hr;
9939 static const float point[3] = {0.0, 0.0, 0.0};
9941 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9942 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9943 if (!hwnd)
9945 skip("Failed to create window\n");
9946 return;
9949 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9950 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9952 hdc = GetDC(hwnd);
9953 if (!hdc)
9955 skip("Failed to get DC\n");
9956 goto cleanup;
9959 if (hwnd2)
9960 hdc2 = GetDC(hwnd2);
9962 gl = LoadLibraryA("opengl32.dll");
9963 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
9965 format = GetPixelFormat(hdc);
9966 ok(format == 0, "new window has pixel format %d\n", format);
9968 ZeroMemory(&pfd, sizeof(pfd));
9969 pfd.nSize = sizeof(pfd);
9970 pfd.nVersion = 1;
9971 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
9972 pfd.iPixelType = PFD_TYPE_RGBA;
9973 pfd.iLayerType = PFD_MAIN_PLANE;
9974 format = ChoosePixelFormat(hdc, &pfd);
9975 if (format <= 0)
9977 skip("no pixel format available\n");
9978 goto cleanup;
9981 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
9983 skip("failed to set pixel format\n");
9984 goto cleanup;
9987 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
9989 skip("failed to set pixel format on second window\n");
9990 if (hdc2)
9992 ReleaseDC(hwnd2, hdc2);
9993 hdc2 = NULL;
9997 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9998 ok(!!d3d9, "Failed to create a D3D object.\n");
10000 test_format = GetPixelFormat(hdc);
10001 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10003 if (!(device = create_device(d3d9, hwnd, NULL)))
10005 skip("Failed to create device\n");
10006 goto cleanup;
10009 test_format = GetPixelFormat(hdc);
10010 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10012 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10013 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10015 test_format = GetPixelFormat(hdc);
10016 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10018 hr = IDirect3DDevice9_BeginScene(device);
10019 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
10021 test_format = GetPixelFormat(hdc);
10022 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10024 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
10025 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10027 test_format = GetPixelFormat(hdc);
10028 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10030 hr = IDirect3DDevice9_EndScene(device);
10031 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
10033 test_format = GetPixelFormat(hdc);
10034 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10036 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10037 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10039 test_format = GetPixelFormat(hdc);
10040 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10042 if (hdc2)
10044 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
10045 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10047 test_format = GetPixelFormat(hdc);
10048 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10050 test_format = GetPixelFormat(hdc2);
10051 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
10054 cleanup:
10055 if (device)
10057 UINT refcount = IDirect3DDevice9_Release(device);
10058 ok(!refcount, "Device has %u references left.\n", refcount);
10060 if (d3d9) IDirect3D9_Release(d3d9);
10061 if (gl) FreeLibrary(gl);
10062 if (hdc) ReleaseDC(hwnd, hdc);
10063 if (hdc2) ReleaseDC(hwnd2, hdc2);
10064 if (hwnd) DestroyWindow(hwnd);
10065 if (hwnd2) DestroyWindow(hwnd2);
10068 static void test_begin_end_state_block(void)
10070 IDirect3DStateBlock9 *stateblock;
10071 IDirect3DDevice9 *device;
10072 IDirect3D9 *d3d;
10073 ULONG refcount;
10074 HWND window;
10075 HRESULT hr;
10077 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10078 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10079 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10080 ok(!!d3d, "Failed to create a D3D object.\n");
10081 if (!(device = create_device(d3d, window, NULL)))
10083 skip("Failed to create a D3D device, skipping tests.\n");
10084 IDirect3D9_Release(d3d);
10085 DestroyWindow(window);
10086 return;
10089 /* Should succeed. */
10090 hr = IDirect3DDevice9_BeginStateBlock(device);
10091 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10093 /* Calling BeginStateBlock() while recording should return
10094 * D3DERR_INVALIDCALL. */
10095 hr = IDirect3DDevice9_BeginStateBlock(device);
10096 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10098 /* Should succeed. */
10099 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10100 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10101 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10102 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10103 "Got unexpected stateblock %p.\n", stateblock);
10104 IDirect3DStateBlock9_Release(stateblock);
10106 /* Calling EndStateBlock() while not recording should return
10107 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10108 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10109 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10110 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10111 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10112 "Got unexpected stateblock %p.\n", 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_shader_constant_apply(void)
10122 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10123 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10124 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10125 IDirect3DStateBlock9 *stateblock;
10126 DWORD vs_version, ps_version;
10127 IDirect3DDevice9 *device;
10128 IDirect3D9 *d3d;
10129 ULONG refcount;
10130 D3DCAPS9 caps;
10131 float ret[4];
10132 HWND window;
10133 HRESULT hr;
10135 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10136 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10137 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10138 ok(!!d3d, "Failed to create a D3D object.\n");
10139 if (!(device = create_device(d3d, window, NULL)))
10141 skip("Failed to create a D3D device, skipping tests.\n");
10142 IDirect3D9_Release(d3d);
10143 DestroyWindow(window);
10144 return;
10147 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10148 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10149 vs_version = caps.VertexShaderVersion & 0xffff;
10150 ps_version = caps.PixelShaderVersion & 0xffff;
10152 if (vs_version)
10154 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10155 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10156 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10157 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10159 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10160 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10161 ok(!memcmp(ret, initial, sizeof(initial)),
10162 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10163 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10164 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10165 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10166 ok(!memcmp(ret, initial, sizeof(initial)),
10167 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10168 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10170 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10171 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10173 if (ps_version)
10175 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10176 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10177 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10178 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10180 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10181 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10182 ok(!memcmp(ret, initial, sizeof(initial)),
10183 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10184 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10185 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10186 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10187 ok(!memcmp(ret, initial, sizeof(initial)),
10188 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10189 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10191 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10192 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10195 hr = IDirect3DDevice9_BeginStateBlock(device);
10196 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10198 if (vs_version)
10200 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10201 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10203 if (ps_version)
10205 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10206 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10209 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10210 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10212 if (vs_version)
10214 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10215 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10216 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10217 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10218 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10219 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10220 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10221 ok(!memcmp(ret, initial, sizeof(initial)),
10222 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10223 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10225 if (ps_version)
10227 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10228 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10229 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10230 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10231 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10232 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10233 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10234 ok(!memcmp(ret, initial, sizeof(initial)),
10235 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10236 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10239 /* Apply doesn't overwrite constants that aren't explicitly set on the
10240 * source stateblock. */
10241 hr = IDirect3DStateBlock9_Apply(stateblock);
10242 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10244 if (vs_version)
10246 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10247 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10248 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10249 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10250 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10251 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10252 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10253 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10254 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10255 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10257 if (ps_version)
10259 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10260 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10261 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10262 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10263 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10264 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10265 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10266 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10267 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10268 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10271 IDirect3DStateBlock9_Release(stateblock);
10272 refcount = IDirect3DDevice9_Release(device);
10273 ok(!refcount, "Device has %u references left.\n", refcount);
10274 IDirect3D9_Release(d3d);
10275 DestroyWindow(window);
10278 static void test_vdecl_apply(void)
10280 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10281 IDirect3DStateBlock9 *stateblock;
10282 IDirect3DDevice9 *device;
10283 IDirect3D9 *d3d;
10284 ULONG refcount;
10285 HWND window;
10286 HRESULT hr;
10288 static const D3DVERTEXELEMENT9 decl1[] =
10290 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10291 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10292 D3DDECL_END(),
10295 static const D3DVERTEXELEMENT9 decl2[] =
10297 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10298 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10299 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10300 D3DDECL_END(),
10303 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10304 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10305 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10306 ok(!!d3d, "Failed to create a D3D object.\n");
10307 if (!(device = create_device(d3d, window, NULL)))
10309 skip("Failed to create a D3D device, skipping tests.\n");
10310 IDirect3D9_Release(d3d);
10311 DestroyWindow(window);
10312 return;
10315 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10316 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10318 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10319 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10321 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10322 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10323 hr = IDirect3DDevice9_BeginStateBlock(device);
10324 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10325 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10326 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10327 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10328 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10329 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10330 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10331 hr = IDirect3DStateBlock9_Apply(stateblock);
10332 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10333 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10334 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10335 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10336 declaration, declaration1);
10337 IDirect3DVertexDeclaration9_Release(declaration);
10339 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10340 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10341 hr = IDirect3DStateBlock9_Capture(stateblock);
10342 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10343 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10344 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10345 hr = IDirect3DStateBlock9_Apply(stateblock);
10346 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10347 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10348 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10349 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10350 declaration, declaration2);
10351 IDirect3DVertexDeclaration9_Release(declaration);
10353 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10354 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10355 hr = IDirect3DStateBlock9_Capture(stateblock);
10356 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10357 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10358 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10359 hr = IDirect3DStateBlock9_Apply(stateblock);
10360 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10361 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10362 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10363 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10364 declaration, declaration2);
10365 IDirect3DVertexDeclaration9_Release(declaration);
10367 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10368 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10369 hr = IDirect3DStateBlock9_Capture(stateblock);
10370 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10371 hr = IDirect3DStateBlock9_Apply(stateblock);
10372 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10373 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10374 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10375 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10377 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10378 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10379 hr = IDirect3DStateBlock9_Capture(stateblock);
10380 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10381 hr = IDirect3DStateBlock9_Apply(stateblock);
10382 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10383 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10384 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10385 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10386 declaration, declaration2);
10387 IDirect3DVertexDeclaration9_Release(declaration);
10389 IDirect3DStateBlock9_Release(stateblock);
10390 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10391 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10392 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10393 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10394 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10395 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10396 hr = IDirect3DStateBlock9_Apply(stateblock);
10397 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10398 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10399 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10400 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10401 declaration, declaration1);
10402 IDirect3DVertexDeclaration9_Release(declaration);
10404 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10405 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10406 hr = IDirect3DStateBlock9_Capture(stateblock);
10407 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10408 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10409 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10410 hr = IDirect3DStateBlock9_Apply(stateblock);
10411 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10412 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10413 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10414 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10415 declaration, declaration2);
10416 IDirect3DVertexDeclaration9_Release(declaration);
10418 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10419 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10420 hr = IDirect3DStateBlock9_Capture(stateblock);
10421 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10422 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10423 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10424 hr = IDirect3DStateBlock9_Apply(stateblock);
10425 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10426 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10427 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10428 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10429 declaration, declaration2);
10430 IDirect3DVertexDeclaration9_Release(declaration);
10432 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10433 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10434 hr = IDirect3DStateBlock9_Capture(stateblock);
10435 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10436 hr = IDirect3DStateBlock9_Apply(stateblock);
10437 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10438 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10439 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10440 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10442 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10443 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10444 hr = IDirect3DStateBlock9_Capture(stateblock);
10445 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10446 hr = IDirect3DStateBlock9_Apply(stateblock);
10447 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10448 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10449 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10450 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10451 declaration, declaration2);
10452 IDirect3DVertexDeclaration9_Release(declaration);
10454 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10455 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10456 IDirect3DVertexDeclaration9_Release(declaration1);
10457 IDirect3DVertexDeclaration9_Release(declaration2);
10458 IDirect3DStateBlock9_Release(stateblock);
10459 refcount = IDirect3DDevice9_Release(device);
10460 ok(!refcount, "Device has %u references left.\n", refcount);
10461 IDirect3D9_Release(d3d);
10462 DestroyWindow(window);
10465 static void test_resource_type(void)
10467 IDirect3DDevice9 *device;
10468 IDirect3DSurface9 *surface;
10469 IDirect3DTexture9 *texture;
10470 IDirect3DCubeTexture9 *cube_texture;
10471 IDirect3DVolume9 *volume;
10472 IDirect3DVolumeTexture9 *volume_texture;
10473 D3DSURFACE_DESC surface_desc;
10474 D3DVOLUME_DESC volume_desc;
10475 D3DRESOURCETYPE type;
10476 IDirect3D9 *d3d;
10477 ULONG refcount;
10478 HWND window;
10479 HRESULT hr;
10480 D3DCAPS9 caps;
10482 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10483 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10484 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10485 ok(!!d3d, "Failed to create a D3D object.\n");
10486 if (!(device = create_device(d3d, window, NULL)))
10488 skip("Failed to create a D3D device, skipping tests.\n");
10489 IDirect3D9_Release(d3d);
10490 DestroyWindow(window);
10491 return;
10494 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10495 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10497 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10498 D3DPOOL_SYSTEMMEM, &surface, NULL);
10499 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10500 type = IDirect3DSurface9_GetType(surface);
10501 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10502 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10503 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10504 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10505 surface_desc.Type);
10506 IDirect3DSurface9_Release(surface);
10508 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10509 D3DPOOL_SYSTEMMEM, &texture, NULL);
10510 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10511 type = IDirect3DTexture9_GetType(texture);
10512 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10514 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10515 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10516 /* The following code crashes, for the sake of completeness:
10517 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10518 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10520 * So applications will not depend on getting the "right" resource type - whatever it
10521 * may be - from the "wrong" vtable. */
10522 type = IDirect3DSurface9_GetType(surface);
10523 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10524 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10525 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10526 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10527 surface_desc.Type);
10528 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10529 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10530 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10531 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10532 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10533 surface_desc.Type);
10534 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10535 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10536 IDirect3DSurface9_Release(surface);
10538 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10539 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10540 type = IDirect3DSurface9_GetType(surface);
10541 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10542 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10543 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10544 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10545 surface_desc.Type);
10546 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10547 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10548 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10549 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10550 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10551 surface_desc.Type);
10552 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10553 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10554 IDirect3DSurface9_Release(surface);
10555 IDirect3DTexture9_Release(texture);
10557 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10559 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10560 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10561 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10562 type = IDirect3DCubeTexture9_GetType(cube_texture);
10563 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10565 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10566 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10567 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10568 type = IDirect3DSurface9_GetType(surface);
10569 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10570 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10571 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10572 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10573 surface_desc.Type);
10574 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10575 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10576 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10577 surface_desc.Type);
10578 IDirect3DSurface9_Release(surface);
10579 IDirect3DCubeTexture9_Release(cube_texture);
10581 else
10582 skip("Cube maps not supported.\n");
10584 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10586 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10587 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10588 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10589 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10590 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10592 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10593 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10594 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10595 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10596 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10597 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10598 volume_desc.Type);
10599 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10600 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10601 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10602 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
10603 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10604 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10605 volume_desc.Type);
10606 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10607 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10608 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10609 IDirect3DVolume9_Release(volume);
10611 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
10612 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10613 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10614 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10615 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10616 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10617 volume_desc.Type);
10618 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10619 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10620 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10621 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
10622 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10623 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10624 volume_desc.Type);
10625 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10626 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10627 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10628 IDirect3DVolume9_Release(volume);
10629 IDirect3DVolumeTexture9_Release(volume_texture);
10631 else
10632 skip("Mipmapped volume maps not supported.\n");
10634 refcount = IDirect3DDevice9_Release(device);
10635 ok(!refcount, "Device has %u references left.\n", refcount);
10636 IDirect3D9_Release(d3d);
10637 DestroyWindow(window);
10640 static void test_mipmap_lock(void)
10642 IDirect3DDevice9 *device;
10643 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
10644 IDirect3DTexture9 *texture, *texture_dst;
10645 IDirect3D9 *d3d;
10646 ULONG refcount;
10647 HWND window;
10648 HRESULT hr;
10649 D3DLOCKED_RECT locked_rect;
10651 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10652 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10653 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10654 ok(!!d3d, "Failed to create a D3D object.\n");
10655 if (!(device = create_device(d3d, window, NULL)))
10657 skip("Failed to create a D3D device, skipping tests.\n");
10658 IDirect3D9_Release(d3d);
10659 DestroyWindow(window);
10660 return;
10663 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10664 D3DPOOL_DEFAULT, &texture_dst, NULL);
10665 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10666 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
10667 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10668 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
10669 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10671 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10672 D3DPOOL_SYSTEMMEM, &texture, NULL);
10673 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10674 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10675 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10676 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
10677 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10679 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
10680 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10681 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
10682 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10683 hr = IDirect3DSurface9_UnlockRect(surface);
10684 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10686 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
10687 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
10688 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
10689 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10691 /* Apparently there's no validation on the container. */
10692 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
10693 (IDirect3DBaseTexture9 *)texture_dst);
10694 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
10696 hr = IDirect3DSurface9_UnlockRect(surface2);
10697 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10699 IDirect3DSurface9_Release(surface_dst2);
10700 IDirect3DSurface9_Release(surface_dst);
10701 IDirect3DSurface9_Release(surface2);
10702 IDirect3DSurface9_Release(surface);
10703 IDirect3DTexture9_Release(texture_dst);
10704 IDirect3DTexture9_Release(texture);
10706 refcount = IDirect3DDevice9_Release(device);
10707 ok(!refcount, "Device has %u references left.\n", refcount);
10708 IDirect3D9_Release(d3d);
10709 DestroyWindow(window);
10712 static void test_writeonly_resource(void)
10714 IDirect3D9 *d3d;
10715 IDirect3DDevice9 *device;
10716 IDirect3DVertexBuffer9 *buffer;
10717 ULONG refcount;
10718 HWND window;
10719 HRESULT hr;
10720 void *ptr;
10721 static const struct
10723 struct vec3 pos;
10725 quad[] =
10727 {{-1.0f, -1.0f, 0.0f}},
10728 {{-1.0f, 1.0f, 0.0f}},
10729 {{ 1.0f, -1.0f, 0.0f}},
10730 {{ 1.0f, 1.0f, 0.0f}}
10733 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10734 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10735 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10736 ok(!!d3d, "Failed to create a D3D object.\n");
10737 if (!(device = create_device(d3d, window, NULL)))
10739 skip("Failed to create a D3D device, skipping tests.\n");
10740 IDirect3D9_Release(d3d);
10741 DestroyWindow(window);
10742 return;
10745 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
10746 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
10747 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
10749 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10750 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10751 memcpy(ptr, quad, sizeof(quad));
10752 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10753 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10754 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
10755 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
10756 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10757 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10759 hr = IDirect3DDevice9_BeginScene(device);
10760 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
10761 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
10762 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10763 hr = IDirect3DDevice9_EndScene(device);
10764 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
10766 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
10767 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10768 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10769 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10770 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10772 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
10773 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10774 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10775 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10776 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10778 refcount = IDirect3DVertexBuffer9_Release(buffer);
10779 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
10780 refcount = IDirect3DDevice9_Release(device);
10781 ok(!refcount, "Device has %u references left.\n", refcount);
10782 IDirect3D9_Release(d3d);
10783 DestroyWindow(window);
10786 static void test_lost_device(void)
10788 struct device_desc device_desc;
10789 IDirect3DDevice9 *device;
10790 IDirect3D9 *d3d;
10791 ULONG refcount;
10792 HWND window;
10793 HRESULT hr;
10794 BOOL ret;
10796 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10797 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10798 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10799 ok(!!d3d, "Failed to create a D3D object.\n");
10800 device_desc.device_window = window;
10801 device_desc.width = registry_mode.dmPelsWidth;
10802 device_desc.height = registry_mode.dmPelsHeight;
10803 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10804 if (!(device = create_device(d3d, window, &device_desc)))
10806 skip("Failed to create a D3D device, skipping tests.\n");
10807 goto done;
10810 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10811 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10812 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10813 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10815 ret = SetForegroundWindow(GetDesktopWindow());
10816 ok(ret, "Failed to set foreground window.\n");
10817 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10818 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10819 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10820 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10822 ret = ShowWindow(window, SW_RESTORE);
10823 ok(ret, "Failed to restore window.\n");
10824 ret = SetForegroundWindow(window);
10825 ok(ret, "Failed to set foreground window.\n");
10826 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10827 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
10828 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10829 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10831 hr = reset_device(device, &device_desc);
10832 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10833 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10834 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10835 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10836 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10838 device_desc.flags = 0;
10839 hr = reset_device(device, &device_desc);
10840 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10841 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10842 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10843 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10844 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10846 ret = SetForegroundWindow(GetDesktopWindow());
10847 ok(ret, "Failed to set foreground window.\n");
10848 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10849 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10850 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10851 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10853 ret = ShowWindow(window, SW_RESTORE);
10854 ok(ret, "Failed to restore window.\n");
10855 ret = SetForegroundWindow(window);
10856 ok(ret, "Failed to set foreground window.\n");
10857 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10858 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10859 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10860 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10862 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10863 hr = reset_device(device, &device_desc);
10864 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10865 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10866 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10867 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10868 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10870 ret = SetForegroundWindow(GetDesktopWindow());
10871 ok(ret, "Failed to set foreground window.\n");
10872 hr = reset_device(device, &device_desc);
10873 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10874 ret = ShowWindow(window, SW_RESTORE);
10875 ok(ret, "Failed to restore window.\n");
10876 ret = SetForegroundWindow(window);
10877 ok(ret, "Failed to set foreground window.\n");
10878 hr = reset_device(device, &device_desc);
10879 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10881 refcount = IDirect3DDevice9_Release(device);
10882 ok(!refcount, "Device has %u references left.\n", refcount);
10883 done:
10884 IDirect3D9_Release(d3d);
10885 DestroyWindow(window);
10888 static void test_resource_priority(void)
10890 IDirect3DDevice9 *device;
10891 IDirect3DSurface9 *surface;
10892 IDirect3DTexture9 *texture;
10893 IDirect3DVertexBuffer9 *buffer;
10894 IDirect3D9 *d3d;
10895 ULONG refcount;
10896 HWND window;
10897 HRESULT hr;
10898 static const struct
10900 D3DPOOL pool;
10901 const char *name;
10902 BOOL can_set_priority;
10904 test_data[] =
10906 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
10907 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
10908 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
10909 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
10911 unsigned int i;
10912 DWORD priority;
10914 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10915 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10916 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10917 ok(!!d3d, "Failed to create a D3D object.\n");
10918 if (!(device = create_device(d3d, window, NULL)))
10920 skip("Failed to create a D3D device, skipping tests.\n");
10921 IDirect3D9_Release(d3d);
10922 DestroyWindow(window);
10923 return;
10926 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
10928 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
10929 test_data[i].pool, &texture, NULL);
10930 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
10931 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10932 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10934 priority = IDirect3DTexture9_GetPriority(texture);
10935 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10936 priority = IDirect3DTexture9_SetPriority(texture, 1);
10937 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10938 priority = IDirect3DTexture9_GetPriority(texture);
10939 if (test_data[i].can_set_priority)
10941 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10942 priority = IDirect3DTexture9_SetPriority(texture, 2);
10943 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10945 else
10946 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10948 priority = IDirect3DSurface9_GetPriority(surface);
10949 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10950 priority = IDirect3DSurface9_SetPriority(surface, 1);
10951 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10952 priority = IDirect3DSurface9_GetPriority(surface);
10953 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10955 IDirect3DSurface9_Release(surface);
10956 IDirect3DTexture9_Release(texture);
10958 if (test_data[i].pool != D3DPOOL_MANAGED)
10960 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
10961 test_data[i].pool, &surface, NULL);
10962 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
10964 priority = IDirect3DSurface9_GetPriority(surface);
10965 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10966 priority = IDirect3DSurface9_SetPriority(surface, 1);
10967 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10968 priority = IDirect3DSurface9_GetPriority(surface);
10969 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10971 IDirect3DSurface9_Release(surface);
10974 if (test_data[i].pool != D3DPOOL_SCRATCH)
10976 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
10977 test_data[i].pool, &buffer, NULL);
10978 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
10980 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10981 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10982 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
10983 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10984 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10985 if (test_data[i].can_set_priority)
10987 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10988 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
10989 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10991 else
10992 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10994 IDirect3DVertexBuffer9_Release(buffer);
10998 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
10999 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11001 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11002 priority = IDirect3DSurface9_GetPriority(surface);
11003 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11004 priority = IDirect3DSurface9_SetPriority(surface, 1);
11005 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11006 priority = IDirect3DSurface9_GetPriority(surface);
11007 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11009 IDirect3DSurface9_Release(surface);
11011 refcount = IDirect3DDevice9_Release(device);
11012 ok(!refcount, "Device has %u references left.\n", refcount);
11013 IDirect3D9_Release(d3d);
11014 DestroyWindow(window);
11017 static void test_swapchain_parameters(void)
11019 IDirect3DDevice9 *device;
11020 IDirect3D9 *d3d;
11021 HWND window;
11022 HRESULT hr;
11023 unsigned int i;
11024 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
11025 IDirect3DSwapChain9 *swapchain;
11026 static const struct
11028 BOOL windowed;
11029 UINT backbuffer_count;
11030 D3DSWAPEFFECT swap_effect;
11031 HRESULT hr;
11033 tests[] =
11035 /* Swap effect 0 is not allowed. */
11036 {TRUE, 1, 0, D3DERR_INVALIDCALL},
11037 {FALSE, 1, 0, D3DERR_INVALIDCALL},
11039 /* All (non-ex) swap effects are allowed in
11040 * windowed and fullscreen mode. */
11041 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11042 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11043 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11044 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11045 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11047 /* Only one backbuffer in copy mode. */
11048 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
11049 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11050 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11051 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11053 /* Ok with the others, in fullscreen and windowed mode. */
11054 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11055 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11056 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11057 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11059 /* D3D9Ex swap effects. */
11060 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11061 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11062 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11063 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11064 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11065 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11067 /* 3 is the highest allowed backbuffer count. */
11068 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11069 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11070 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11071 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11072 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11075 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11076 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11077 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11078 ok(!!d3d, "Failed to create a D3D object.\n");
11079 if (!(device = create_device(d3d, window, NULL)))
11081 skip("Failed to create a D3D device, skipping tests.\n");
11082 IDirect3D9_Release(d3d);
11083 DestroyWindow(window);
11084 return;
11086 IDirect3DDevice9_Release(device);
11088 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11089 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11090 present_parameters_windowed.hDeviceWindow = window;
11091 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11092 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11093 present_parameters_windowed.Windowed = TRUE;
11094 present_parameters_windowed.BackBufferCount = 1;
11096 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
11098 memset(&present_parameters, 0, sizeof(present_parameters));
11099 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11100 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11101 present_parameters.hDeviceWindow = window;
11102 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11104 present_parameters.SwapEffect = tests[i].swap_effect;
11105 present_parameters.Windowed = tests[i].windowed;
11106 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11108 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11109 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11110 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11111 if (SUCCEEDED(hr))
11113 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11115 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11116 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11118 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11119 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11120 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11121 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11122 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11123 bb_count, present_parameters2.BackBufferCount, i);
11124 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11125 tests[i].windowed, present_parameters2.Windowed, i);
11127 IDirect3DSwapChain9_Release(swapchain);
11128 IDirect3DDevice9_Release(device);
11131 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11132 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11133 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11135 memset(&present_parameters, 0, sizeof(present_parameters));
11136 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11137 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11138 present_parameters.hDeviceWindow = window;
11139 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11141 present_parameters.SwapEffect = tests[i].swap_effect;
11142 present_parameters.Windowed = tests[i].windowed;
11143 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11145 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11146 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11148 if (FAILED(hr))
11150 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11151 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11153 IDirect3DDevice9_Release(device);
11156 IDirect3D9_Release(d3d);
11157 DestroyWindow(window);
11160 static void test_check_device_format(void)
11162 IDirect3D9 *d3d;
11163 HRESULT hr;
11165 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11166 ok(!!d3d, "Failed to create a D3D object.\n");
11168 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11169 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11171 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11173 else
11175 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11176 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11177 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11178 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11179 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11180 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11183 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11184 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11185 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11186 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11187 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11188 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11189 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11190 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11191 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11193 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11194 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11195 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11196 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11197 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11198 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11199 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11200 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11201 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11203 IDirect3D9_Release(d3d);
11206 static void test_miptree_layout(void)
11208 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11209 IDirect3DCubeTexture9 *texture_cube;
11210 IDirect3DTexture9 *texture_2d;
11211 IDirect3DDevice9 *device;
11212 D3DLOCKED_RECT map_desc;
11213 BYTE *base = NULL;
11214 IDirect3D9 *d3d;
11215 D3DCAPS9 caps;
11216 UINT refcount;
11217 HWND window;
11218 HRESULT hr;
11220 static const struct
11222 D3DFORMAT format;
11223 const char *name;
11225 formats[] =
11227 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11228 {D3DFMT_A8, "D3DFMT_A8"},
11229 {D3DFMT_L8, "D3DFMT_L8"},
11230 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11231 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11233 static const struct
11235 D3DPOOL pool;
11236 const char *name;
11238 pools[] =
11240 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11241 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11242 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11245 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11246 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11247 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11248 ok(!!d3d, "Failed to create a D3D object.\n");
11249 if (!(device = create_device(d3d, window, NULL)))
11251 skip("Failed to create a D3D device, skipping tests.\n");
11252 goto done;
11255 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11256 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11258 base_dimension = 257;
11259 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11261 skip("Using power of two base dimension.\n");
11262 base_dimension = 256;
11265 for (format_idx = 0; format_idx < sizeof(formats) / sizeof(*formats); ++format_idx)
11267 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11268 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11270 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11271 continue;
11274 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11276 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11277 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11278 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11279 pools[pool_idx].name, formats[format_idx].name, hr);
11281 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11282 for (i = 0, offset = 0; i < level_count; ++i)
11284 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11285 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11286 pools[pool_idx].name, formats[format_idx].name, i, hr);
11288 if (!i)
11289 base = map_desc.pBits;
11290 else
11291 ok(map_desc.pBits == base + offset,
11292 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11293 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11294 offset += (base_dimension >> i) * map_desc.Pitch;
11296 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11297 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11298 pools[pool_idx].name, formats[format_idx].name, i, hr);
11301 IDirect3DTexture9_Release(texture_2d);
11304 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11305 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11307 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11308 continue;
11311 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11313 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11314 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11315 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11316 pools[pool_idx].name, formats[format_idx].name, hr);
11318 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11319 for (i = 0, offset = 0; i < 6; ++i)
11321 for (j = 0; j < level_count; ++j)
11323 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11324 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11325 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11327 if (!i && !j)
11328 base = map_desc.pBits;
11329 else
11330 ok(map_desc.pBits == base + offset,
11331 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11332 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11333 offset += (base_dimension >> j) * map_desc.Pitch;
11335 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11336 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11337 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11339 offset = (offset + 15) & ~15;
11342 IDirect3DCubeTexture9_Release(texture_cube);
11346 refcount = IDirect3DDevice9_Release(device);
11347 ok(!refcount, "Device has %u references left.\n", refcount);
11348 done:
11349 IDirect3D9_Release(d3d);
11350 DestroyWindow(window);
11353 static void test_get_render_target_data(void)
11355 IDirect3DSurface9 *offscreen_surface, *render_target;
11356 IDirect3DDevice9 *device;
11357 IDirect3D9 *d3d;
11358 UINT refcount;
11359 HWND window;
11360 HRESULT hr;
11362 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11363 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11364 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11365 ok(!!d3d, "Failed to create a D3D object.\n");
11366 if (!(device = create_device(d3d, window, NULL)))
11368 skip("Failed to create a D3D device.\n");
11369 IDirect3D9_Release(d3d);
11370 DestroyWindow(window);
11371 return;
11374 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11375 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11376 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11378 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11379 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11380 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11382 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11383 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11385 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11386 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11388 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11389 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11391 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11392 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11394 IDirect3DSurface9_Release(render_target);
11395 IDirect3DSurface9_Release(offscreen_surface);
11396 refcount = IDirect3DDevice9_Release(device);
11397 ok(!refcount, "Device has %u references left.\n", refcount);
11398 IDirect3D9_Release(d3d);
11399 DestroyWindow(window);
11402 static void test_render_target_device_mismatch(void)
11404 IDirect3DDevice9 *device, *device2;
11405 IDirect3DSurface9 *surface, *rt;
11406 IDirect3D9 *d3d;
11407 UINT refcount;
11408 HWND window;
11409 HRESULT hr;
11411 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11412 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11413 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11414 ok(!!d3d, "Failed to create a D3D object.\n");
11415 if (!(device = create_device(d3d, window, NULL)))
11417 skip("Failed to create a D3D device.\n");
11418 IDirect3D9_Release(d3d);
11419 DestroyWindow(window);
11420 return;
11423 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
11424 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11426 device2 = create_device(d3d, window, NULL);
11427 ok(!!device2, "Failed to create a D3D device.\n");
11429 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11430 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11431 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11433 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11434 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11436 IDirect3DSurface9_Release(surface);
11438 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11439 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11441 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11442 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11444 IDirect3DSurface9_Release(surface);
11446 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11447 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11448 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11449 IDirect3DSurface9_Release(surface);
11450 IDirect3DSurface9_Release(rt);
11452 refcount = IDirect3DDevice9_Release(device);
11453 ok(!refcount, "Device has %u references left.\n", refcount);
11454 refcount = IDirect3DDevice9_Release(device2);
11455 ok(!refcount, "Device has %u references left.\n", refcount);
11456 IDirect3D9_Release(d3d);
11457 DestroyWindow(window);
11460 static void test_format_unknown(void)
11462 IDirect3DDevice9 *device;
11463 IDirect3D9 *d3d;
11464 UINT refcount;
11465 HWND window;
11466 void *iface;
11467 HRESULT hr;
11469 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11470 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11471 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11472 ok(!!d3d, "Failed to create a D3D object.\n");
11473 if (!(device = create_device(d3d, window, NULL)))
11475 skip("Failed to create a D3D device.\n");
11476 IDirect3D9_Release(d3d);
11477 DestroyWindow(window);
11478 return;
11481 iface = (void *)0xdeadbeef;
11482 hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64,
11483 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
11484 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11485 ok(!iface, "Got unexpected iface %p.\n", iface);
11487 iface = (void *)0xdeadbeef;
11488 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 64, 64,
11489 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
11490 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11491 ok(!iface, "Got unexpected iface %p.\n", iface);
11493 iface = (void *)0xdeadbeef;
11494 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
11495 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
11496 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11497 ok(!iface, "Got unexpected iface %p.\n", iface);
11499 iface = (void *)0xdeadbeef;
11500 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
11501 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
11502 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11503 ok(!iface, "Got unexpected iface %p.\n", iface);
11505 iface = (void *)0xdeadbeef;
11506 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 1, 0,
11507 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
11508 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11509 ok(!iface, "Got unexpected iface %p.\n", iface);
11511 iface = (void *)0xdeadbeef;
11512 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
11513 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
11514 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11515 ok(!iface, "Got unexpected iface %p.\n", iface);
11517 refcount = IDirect3DDevice9_Release(device);
11518 ok(!refcount, "Device has %u references left.\n", refcount);
11519 IDirect3D9_Release(d3d);
11520 DestroyWindow(window);
11523 START_TEST(device)
11525 WNDCLASSA wc = {0};
11526 IDirect3D9 *d3d9;
11527 DEVMODEW current_mode;
11529 memset(&current_mode, 0, sizeof(current_mode));
11530 current_mode.dmSize = sizeof(current_mode);
11531 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
11532 registry_mode.dmSize = sizeof(registry_mode);
11533 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
11534 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
11535 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
11537 skip("Current mode does not match registry mode, skipping test.\n");
11538 return;
11541 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
11543 skip("could not create D3D9 object\n");
11544 return;
11546 IDirect3D9_Release(d3d9);
11548 wc.lpfnWndProc = DefWindowProcA;
11549 wc.lpszClassName = "d3d9_test_wc";
11550 RegisterClassA(&wc);
11552 test_get_set_vertex_declaration();
11553 test_get_declaration();
11554 test_fvf_decl_conversion();
11555 test_fvf_decl_management();
11556 test_vertex_declaration_alignment();
11557 test_unused_declaration_type();
11558 test_fpu_setup();
11559 test_multi_device();
11560 test_display_formats();
11561 test_display_modes();
11562 test_swapchain();
11563 test_refcount();
11564 test_mipmap_levels();
11565 test_checkdevicemultisampletype();
11566 test_invalid_multisample();
11567 test_cursor();
11568 test_cursor_pos();
11569 test_reset_fullscreen();
11570 test_reset();
11571 test_scene();
11572 test_limits();
11573 test_depthstenciltest();
11574 test_get_rt();
11575 test_draw_primitive();
11576 test_null_stream();
11577 test_lights();
11578 test_set_stream_source();
11579 test_scissor_size();
11580 test_wndproc();
11581 test_wndproc_windowed();
11582 test_window_style();
11583 test_mode_change();
11584 test_device_window_reset();
11585 test_reset_resources();
11586 test_set_rt_vp_scissor();
11587 test_volume_get_container();
11588 test_volume_resource();
11589 test_vb_lock_flags();
11590 test_vertex_buffer_alignment();
11591 test_query_support();
11592 test_occlusion_query();
11593 test_timestamp_query();
11594 test_get_set_vertex_shader();
11595 test_vertex_shader_constant();
11596 test_get_set_pixel_shader();
11597 test_pixel_shader_constant();
11598 test_unsupported_shaders();
11599 test_texture_stage_states();
11600 test_cube_textures();
11601 test_mipmap_gen();
11602 test_filter();
11603 test_get_set_texture();
11604 test_lod();
11605 test_surface_get_container();
11606 test_surface_alignment();
11607 test_lockrect_offset();
11608 test_lockrect_invalid();
11609 test_private_data();
11610 test_getdc();
11611 test_surface_dimensions();
11612 test_surface_format_null();
11613 test_surface_double_unlock();
11614 test_surface_blocks();
11615 test_set_palette();
11616 test_swvp_buffer();
11617 test_managed_buffer();
11618 test_npot_textures();
11619 test_vidmem_accounting();
11620 test_volume_locking();
11621 test_update_volumetexture();
11622 test_create_rt_ds_fail();
11623 test_volume_blocks();
11624 test_lockbox_invalid();
11625 test_shared_handle();
11626 test_pixel_format();
11627 test_begin_end_state_block();
11628 test_shader_constant_apply();
11629 test_vdecl_apply();
11630 test_resource_type();
11631 test_mipmap_lock();
11632 test_writeonly_resource();
11633 test_lost_device();
11634 test_resource_priority();
11635 test_swapchain_parameters();
11636 test_check_device_format();
11637 test_miptree_layout();
11638 test_get_render_target_data();
11639 test_render_target_device_mismatch();
11640 test_format_unknown();
11642 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));