d3d9: Return D3D_OK from UnlockRect() for not locked textures.
[wine.git] / dlls / d3d9 / tests / device.c
blob758e5c8bdb1c147a6bfd2be154ef649860bb5c22
1 /*
2 * Copyright (C) 2006 Ivan Gyurdiev
3 * Copyright (C) 2006 Vitaliy Margolen
4 * Copyright (C) 2006 Chris Robinson
5 * Copyright 2006-2008, 2010-2011, 2013 Stefan Dösinger for CodeWeavers
6 * Copyright 2005, 2006, 2007 Henri Verbeet
7 * Copyright 2013-2014 Henri Verbeet for CodeWeavers
8 * Copyright (C) 2008 Rico Schüller
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WINVER 0x0602 /* for CURSOR_SUPPRESSED */
26 #define COBJMACROS
27 #include <d3d9.h>
28 #include "wine/test.h"
30 struct vec3
32 float x, y, z;
35 #define CREATE_DEVICE_FULLSCREEN 0x01
36 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
37 #define CREATE_DEVICE_FPU_PRESERVE 0x04
38 #define CREATE_DEVICE_SWVP_ONLY 0x08
40 struct device_desc
42 HWND device_window;
43 unsigned int width;
44 unsigned int height;
45 DWORD flags;
48 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
49 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
51 static DEVMODEW registry_mode;
53 static const DWORD simple_vs[] =
55 0xfffe0101, /* vs_1_1 */
56 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
57 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
58 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
59 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
60 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
61 0x0000ffff, /* end */
64 static const DWORD simple_ps[] =
66 0xffff0101, /* ps_1_1 */
67 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
68 0x00000042, 0xb00f0000, /* tex t0 */
69 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
70 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
71 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
72 0x0000ffff, /* end */
75 static int get_refcount(IUnknown *object)
77 IUnknown_AddRef( object );
78 return IUnknown_Release( object );
81 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
83 unsigned int element_count, i;
84 D3DVERTEXELEMENT9 *elements;
85 BOOL equal = TRUE;
86 HRESULT hr;
88 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
89 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
90 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
91 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
92 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
94 for (i = 0; i < element_count; ++i)
96 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
98 equal = FALSE;
99 break;
103 if (!equal)
105 for (i = 0; i < element_count; ++i)
107 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
108 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
109 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
113 HeapFree(GetProcessHeap(), 0, elements);
114 return equal;
117 /* try to make sure pending X events have been processed before continuing */
118 static void flush_events(void)
120 MSG msg;
121 int diff = 200;
122 int min_timeout = 100;
123 DWORD time = GetTickCount() + diff;
125 while (diff > 0)
127 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
128 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
129 diff = time - GetTickCount();
133 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
135 D3DPRESENT_PARAMETERS present_parameters = {0};
136 IDirect3DDevice9 *device;
137 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
139 present_parameters.BackBufferWidth = 640;
140 present_parameters.BackBufferHeight = 480;
141 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
142 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
143 present_parameters.hDeviceWindow = focus_window;
144 present_parameters.Windowed = TRUE;
145 present_parameters.EnableAutoDepthStencil = TRUE;
146 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
148 if (desc)
150 present_parameters.BackBufferWidth = desc->width;
151 present_parameters.BackBufferHeight = desc->height;
152 present_parameters.hDeviceWindow = desc->device_window;
153 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
154 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
155 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
156 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
157 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
158 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
159 behavior_flags |= D3DCREATE_FPU_PRESERVE;
162 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
163 behavior_flags, &present_parameters, &device)))
164 return device;
166 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
167 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
168 behavior_flags, &present_parameters, &device)))
169 return device;
171 if (desc && desc->flags & CREATE_DEVICE_SWVP_ONLY)
172 return NULL;
173 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
175 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
176 behavior_flags, &present_parameters, &device)))
177 return device;
179 return NULL;
182 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
184 D3DPRESENT_PARAMETERS present_parameters = {0};
186 present_parameters.BackBufferWidth = 640;
187 present_parameters.BackBufferHeight = 480;
188 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
189 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
190 present_parameters.hDeviceWindow = NULL;
191 present_parameters.Windowed = TRUE;
192 present_parameters.EnableAutoDepthStencil = TRUE;
193 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
195 if (desc)
197 present_parameters.BackBufferWidth = desc->width;
198 present_parameters.BackBufferHeight = desc->height;
199 present_parameters.hDeviceWindow = desc->device_window;
200 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
203 return IDirect3DDevice9_Reset(device, &present_parameters);
206 #define CHECK_CALL(r,c,d,rc) \
207 if (SUCCEEDED(r)) {\
208 int tmp1 = get_refcount( (IUnknown *)d ); \
209 int rc_new = rc; \
210 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
211 } else {\
212 trace("%s failed: %08x\n", c, r); \
215 #define CHECK_RELEASE(obj,d,rc) \
216 if (obj) { \
217 int tmp1, rc_new = rc; \
218 IUnknown_Release( (IUnknown*)obj ); \
219 tmp1 = get_refcount( (IUnknown *)d ); \
220 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
223 #define CHECK_REFCOUNT(obj,rc) \
225 int rc_new = rc; \
226 int count = get_refcount( (IUnknown *)obj ); \
227 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
230 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
232 int rc_new = rc; \
233 int count = IUnknown_Release( (IUnknown *)obj ); \
234 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
237 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
239 int rc_new = rc; \
240 int count = IUnknown_AddRef( (IUnknown *)obj ); \
241 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
244 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
246 void *container_ptr = (void *)0x1337c0d3; \
247 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
248 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
249 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
250 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
253 static void test_get_set_vertex_declaration(void)
255 IDirect3DVertexDeclaration9 *declaration, *tmp;
256 ULONG refcount, expected_refcount;
257 IDirect3DDevice9 *device;
258 IDirect3D9 *d3d;
259 HWND window;
260 HRESULT hr;
262 static const D3DVERTEXELEMENT9 simple_decl[] =
264 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
265 D3DDECL_END()
268 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
269 0, 0, 640, 480, NULL, NULL, NULL, NULL);
270 d3d = Direct3DCreate9(D3D_SDK_VERSION);
271 ok(!!d3d, "Failed to create a D3D object.\n");
272 if (!(device = create_device(d3d, window, NULL)))
274 skip("Failed to create a D3D device, skipping tests.\n");
275 goto done;
278 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
279 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
281 /* SetVertexDeclaration() should not touch the declaration's refcount. */
282 expected_refcount = get_refcount((IUnknown *)declaration);
283 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
284 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
285 refcount = get_refcount((IUnknown *)declaration);
286 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
288 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
289 tmp = NULL;
290 expected_refcount = refcount + 1;
291 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
292 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
293 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
294 refcount = get_refcount((IUnknown *)declaration);
295 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
296 IDirect3DVertexDeclaration9_Release(tmp);
298 IDirect3DVertexDeclaration9_Release(declaration);
299 refcount = IDirect3DDevice9_Release(device);
300 ok(!refcount, "Device has %u references left.\n", refcount);
301 done:
302 IDirect3D9_Release(d3d);
303 DestroyWindow(window);
306 static void test_get_declaration(void)
308 unsigned int element_count, expected_element_count;
309 IDirect3DVertexDeclaration9 *declaration;
310 D3DVERTEXELEMENT9 *elements;
311 IDirect3DDevice9 *device;
312 IDirect3D9 *d3d;
313 ULONG refcount;
314 HWND window;
315 HRESULT hr;
317 static const D3DVERTEXELEMENT9 simple_decl[] =
319 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
320 D3DDECL_END()
323 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
324 0, 0, 640, 480, NULL, NULL, NULL, NULL);
325 d3d = Direct3DCreate9(D3D_SDK_VERSION);
326 ok(!!d3d, "Failed to create a D3D object.\n");
327 if (!(device = create_device(d3d, window, NULL)))
329 skip("Failed to create a D3D device, skipping tests.\n");
330 goto done;
333 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
334 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
336 /* First test only getting the number of elements. */
337 element_count = 0x1337c0de;
338 expected_element_count = sizeof(simple_decl) / sizeof(*simple_decl);
339 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
340 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
341 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
342 element_count, expected_element_count);
344 element_count = 0;
345 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
346 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
347 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
348 element_count, expected_element_count);
350 /* Also test the returned data. */
351 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
353 element_count = 0x1337c0de;
354 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
355 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
356 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
357 element_count, expected_element_count);
358 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
359 "Original and returned vertexdeclarations are not the same.\n");
361 memset(elements, 0, sizeof(simple_decl));
363 element_count = 0;
364 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
365 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
366 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
367 element_count, expected_element_count);
368 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
369 "Original and returned vertexdeclarations are not the same.\n");
371 HeapFree(GetProcessHeap(), 0, elements);
372 IDirect3DVertexDeclaration9_Release(declaration);
373 refcount = IDirect3DDevice9_Release(device);
374 ok(!refcount, "Device has %u references left.\n", refcount);
375 done:
376 IDirect3D9_Release(d3d);
377 DestroyWindow(window);
380 static void test_fvf_decl_conversion(void)
382 IDirect3DVertexDeclaration9 *default_decl;
383 IDirect3DVertexDeclaration9 *declaration;
384 IDirect3DDevice9 *device;
385 IDirect3D9 *d3d;
386 ULONG refcount;
387 unsigned int i;
388 HWND window;
389 HRESULT hr;
391 static const D3DVERTEXELEMENT9 default_elements[] =
393 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
394 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
395 D3DDECL_END()
397 /* Test conversions from vertex declaration to an FVF. For some reason
398 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
399 * forced to 0 - maybe this is configuration specific. */
400 static const struct
402 D3DVERTEXELEMENT9 elements[7];
403 DWORD fvf;
404 BOOL todo;
406 decl_to_fvf_tests[] =
408 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
409 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
410 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
411 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
412 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
413 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
414 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
415 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
416 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
417 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
418 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
419 /* No FVF mapping available. */
420 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
421 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
422 /* Try empty declaration. */
423 {{ D3DDECL_END()}, 0, FALSE},
424 /* Make sure textures of different sizes work. */
425 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
426 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
427 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
428 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
429 /* Make sure the TEXCOORD index works correctly - try several textures. */
432 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
433 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
434 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
435 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
436 D3DDECL_END(),
437 }, 0, FALSE,
439 /* Now try a combination test. */
442 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
443 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
444 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
445 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
446 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
447 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
448 D3DDECL_END(),
449 }, 0, FALSE,
452 /* Test conversions from FVF to a vertex declaration. These seem to always
453 * occur internally. A new declaration object is created if necessary. */
454 static const struct
456 DWORD fvf;
457 D3DVERTEXELEMENT9 elements[7];
459 fvf_to_decl_tests[] =
461 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
462 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
463 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
465 D3DFVF_XYZB5,
467 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
468 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
469 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
470 D3DDECL_END(),
474 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
476 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
477 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
478 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
479 D3DDECL_END(),
483 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
485 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
486 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
487 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
488 D3DDECL_END(),
492 D3DFVF_XYZB1,
494 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
495 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
496 D3DDECL_END(),
500 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
502 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
503 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
504 D3DDECL_END(),
508 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
510 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
511 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
512 D3DDECL_END(),
516 D3DFVF_XYZB2,
518 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
519 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
520 D3DDECL_END(),
524 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
526 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
527 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
528 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
529 D3DDECL_END(),
533 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
535 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
536 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
537 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
538 D3DDECL_END(),
542 D3DFVF_XYZB3,
544 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
545 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
546 D3DDECL_END(),
550 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
552 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
553 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
554 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
555 D3DDECL_END(),
559 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
561 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
562 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
563 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
564 D3DDECL_END(),
568 D3DFVF_XYZB4,
570 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
571 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
572 D3DDECL_END(),
576 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
578 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
579 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
580 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
581 D3DDECL_END(),
585 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
587 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
588 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
589 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
590 D3DDECL_END(),
593 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
594 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
595 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
596 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
597 /* Make sure textures of different sizes work. */
599 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
600 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
603 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
604 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
607 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
608 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
611 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
612 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
614 /* Make sure the TEXCOORD index works correctly - try several textures. */
616 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
617 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
619 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
620 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
621 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
622 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
623 D3DDECL_END(),
626 /* Now try a combination test. */
628 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
629 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
631 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
632 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
633 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
634 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
635 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
636 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
637 D3DDECL_END(),
642 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
643 0, 0, 640, 480, NULL, NULL, NULL, NULL);
644 d3d = Direct3DCreate9(D3D_SDK_VERSION);
645 ok(!!d3d, "Failed to create a D3D object.\n");
646 if (!(device = create_device(d3d, window, NULL)))
648 skip("Failed to create a D3D device, skipping tests.\n");
649 goto done;
652 for (i = 0; i < sizeof(decl_to_fvf_tests) / sizeof(*decl_to_fvf_tests); ++i)
654 DWORD fvf = 0xdeadbeef;
655 HRESULT hr;
657 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
658 * back to 0. */
659 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
660 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
662 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
663 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
664 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
665 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
667 /* Check the FVF. */
668 hr = IDirect3DDevice9_GetFVF(device, &fvf);
669 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
671 todo_wine_if (decl_to_fvf_tests[i].todo)
672 ok(fvf == decl_to_fvf_tests[i].fvf,
673 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
674 i, fvf, decl_to_fvf_tests[i].fvf);
676 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
677 IDirect3DVertexDeclaration9_Release(declaration);
680 /* Create a default declaration and FVF that does not match any of the
681 * tests. */
682 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
683 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
685 for (i = 0; i < sizeof(fvf_to_decl_tests) / sizeof(*fvf_to_decl_tests); ++i)
687 /* Set a default declaration to make sure it is changed. */
688 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
689 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
691 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
692 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
694 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
695 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
696 ok(!!declaration && declaration != default_decl,
697 "Test %u: Got unexpected declaration %p.\n", i, declaration);
698 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
699 "Test %u: Declaration does not match.\n", i);
700 IDirect3DVertexDeclaration9_Release(declaration);
703 /* Setting the FVF to 0 should result in no change to the default decl. */
704 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
705 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
706 hr = IDirect3DDevice9_SetFVF(device, 0);
707 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
708 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
709 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
710 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
711 IDirect3DVertexDeclaration9_Release(declaration);
713 IDirect3DVertexDeclaration9_Release(default_decl);
714 refcount = IDirect3DDevice9_Release(device);
715 ok(!refcount, "Device has %u references left.\n", refcount);
716 done:
717 IDirect3D9_Release(d3d);
718 DestroyWindow(window);
721 /* Check whether a declaration converted from FVF is shared.
722 * Check whether refcounts behave as expected. */
723 static void test_fvf_decl_management(void)
725 IDirect3DVertexDeclaration9 *declaration1;
726 IDirect3DVertexDeclaration9 *declaration2;
727 IDirect3DVertexDeclaration9 *declaration3;
728 IDirect3DVertexDeclaration9 *declaration4;
729 IDirect3DDevice9 *device;
730 IDirect3D9 *d3d;
731 ULONG refcount;
732 HWND window;
733 HRESULT hr;
735 static const D3DVERTEXELEMENT9 test_elements1[] =
736 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
737 static const D3DVERTEXELEMENT9 test_elements2[] =
738 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
740 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
741 0, 0, 640, 480, NULL, NULL, NULL, NULL);
742 d3d = Direct3DCreate9(D3D_SDK_VERSION);
743 ok(!!d3d, "Failed to create a D3D object.\n");
744 if (!(device = create_device(d3d, window, NULL)))
746 skip("Failed to create a D3D device, skipping tests.\n");
747 goto done;
750 /* Clear down any current vertex declaration. */
751 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
752 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
753 /* Conversion. */
754 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
755 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
756 /* Get converted decl (#1). */
757 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
758 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
759 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
760 /* Get converted decl again (#2). */
761 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
762 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
763 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
765 /* Conversion. */
766 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
767 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
768 /* Get converted decl (#3). */
769 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
770 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
771 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
772 /* The contents should correspond to the second conversion. */
773 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
774 /* Re-Check if the first decl was overwritten by the new Get(). */
775 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
777 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
778 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
779 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
780 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
781 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
783 refcount = get_refcount((IUnknown*)declaration1);
784 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
785 refcount = get_refcount((IUnknown*)declaration2);
786 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
787 refcount = get_refcount((IUnknown*)declaration3);
788 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
789 refcount = get_refcount((IUnknown*)declaration4);
790 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
792 IDirect3DVertexDeclaration9_Release(declaration4);
793 IDirect3DVertexDeclaration9_Release(declaration3);
794 IDirect3DVertexDeclaration9_Release(declaration2);
795 IDirect3DVertexDeclaration9_Release(declaration1);
797 refcount = IDirect3DDevice9_Release(device);
798 ok(!refcount, "Device has %u references left.\n", refcount);
799 done:
800 IDirect3D9_Release(d3d);
801 DestroyWindow(window);
804 static void test_vertex_declaration_alignment(void)
806 IDirect3DVertexDeclaration9 *declaration;
807 IDirect3DDevice9 *device;
808 IDirect3D9 *d3d;
809 unsigned int i;
810 ULONG refcount;
811 HWND window;
812 HRESULT hr;
814 static const struct
816 D3DVERTEXELEMENT9 elements[3];
817 HRESULT hr;
819 test_data[] =
823 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
824 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
825 D3DDECL_END(),
826 }, D3D_OK,
830 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
831 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
832 D3DDECL_END(),
833 }, E_FAIL,
837 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
838 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
839 D3DDECL_END(),
840 }, E_FAIL,
844 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
845 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
846 D3DDECL_END(),
847 }, E_FAIL,
851 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
852 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
853 D3DDECL_END(),
854 }, D3D_OK,
858 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
859 0, 0, 640, 480, NULL, NULL, NULL, NULL);
860 d3d = Direct3DCreate9(D3D_SDK_VERSION);
861 ok(!!d3d, "Failed to create a D3D object.\n");
862 if (!(device = create_device(d3d, window, NULL)))
864 skip("Failed to create a D3D device, skipping tests.\n");
865 goto done;
868 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
870 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
871 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
872 if (SUCCEEDED(hr))
873 IDirect3DVertexDeclaration9_Release(declaration);
876 refcount = IDirect3DDevice9_Release(device);
877 ok(!refcount, "Device has %u references left.\n", refcount);
878 done:
879 IDirect3D9_Release(d3d);
880 DestroyWindow(window);
883 static void test_unused_declaration_type(void)
885 IDirect3DVertexDeclaration9 *declaration;
886 IDirect3DDevice9 *device;
887 IDirect3D9 *d3d;
888 unsigned int i;
889 ULONG refcount;
890 HWND window;
891 HRESULT hr;
893 static const D3DVERTEXELEMENT9 test_elements[][3] =
896 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
897 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
898 D3DDECL_END(),
901 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
902 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
903 D3DDECL_END(),
906 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
907 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
908 D3DDECL_END(),
911 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
912 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
913 D3DDECL_END(),
916 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
917 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
918 D3DDECL_END(),
921 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
922 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
923 D3DDECL_END(),
926 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
927 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
928 D3DDECL_END(),
932 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
933 0, 0, 640, 480, NULL, NULL, NULL, NULL);
934 d3d = Direct3DCreate9(D3D_SDK_VERSION);
935 ok(!!d3d, "Failed to create a D3D object.\n");
936 if (!(device = create_device(d3d, window, NULL)))
938 skip("Failed to create a D3D device, skipping tests.\n");
939 goto done;
942 for (i = 0; i < sizeof(test_elements) / sizeof(*test_elements); ++i)
944 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
945 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
948 refcount = IDirect3DDevice9_Release(device);
949 ok(!refcount, "Device has %u references left.\n", refcount);
950 done:
951 IDirect3D9_Release(d3d);
952 DestroyWindow(window);
955 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
957 IDirect3DBaseTexture9* texture = NULL;
958 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
959 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
961 if (SUCCEEDED(hr)) {
962 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
963 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
964 } else
965 trace("CreateTexture failed: %08x\n", hr);
967 if (texture) IDirect3DBaseTexture9_Release( texture );
970 static void test_mipmap_levels(void)
972 IDirect3DDevice9 *device;
973 IDirect3D9 *d3d;
974 ULONG refcount;
975 HWND window;
977 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
978 0, 0, 640, 480, NULL, NULL, NULL, NULL);
979 ok(!!window, "Failed to create a window.\n");
980 d3d = Direct3DCreate9(D3D_SDK_VERSION);
981 ok(!!d3d, "Failed to create a D3D object.\n");
982 if (!(device = create_device(d3d, window, NULL)))
984 skip("Failed to create a 3D device, skipping test.\n");
985 goto cleanup;
988 check_mipmap_levels(device, 32, 32, 6);
989 check_mipmap_levels(device, 256, 1, 9);
990 check_mipmap_levels(device, 1, 256, 9);
991 check_mipmap_levels(device, 1, 1, 1);
993 refcount = IDirect3DDevice9_Release(device);
994 ok(!refcount, "Device has %u references left.\n", refcount);
995 cleanup:
996 IDirect3D9_Release(d3d);
997 DestroyWindow(window);
1000 static void test_checkdevicemultisampletype(void)
1002 DWORD quality_levels;
1003 IDirect3D9 *d3d;
1004 HWND window;
1005 HRESULT hr;
1007 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1008 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1009 ok(!!window, "Failed to create a window.\n");
1010 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1011 ok(!!d3d, "Failed to create a D3D object.\n");
1013 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1014 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL) == D3DERR_NOTAVAILABLE)
1016 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
1017 goto cleanup;
1020 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1021 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE, NULL);
1022 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1023 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1024 65536, TRUE, D3DMULTISAMPLE_NONE, NULL);
1025 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1027 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1028 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, NULL);
1029 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1031 quality_levels = 0;
1032 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1033 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1034 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1035 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1036 quality_levels = 0;
1037 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1038 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1039 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1040 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1042 quality_levels = 0;
1043 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1044 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, NULL);
1045 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1046 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1047 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels);
1048 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1049 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1051 quality_levels = 0;
1052 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1053 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1054 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1055 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1056 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels);
1057 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1058 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1060 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1061 quality_levels = 0;
1062 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1063 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1064 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1065 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1066 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, &quality_levels);
1067 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1068 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1070 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1071 D3DFMT_X8R8G8B8, TRUE, 65536, NULL);
1072 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1074 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1075 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1076 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1078 cleanup:
1079 IDirect3D9_Release(d3d);
1080 DestroyWindow(window);
1083 static void test_invalid_multisample(void)
1085 IDirect3DDevice9 *device;
1086 IDirect3DSurface9 *rt;
1087 DWORD quality_levels;
1088 IDirect3D9 *d3d;
1089 BOOL available;
1090 ULONG refcount;
1091 HWND window;
1092 HRESULT hr;
1094 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1095 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1096 ok(!!window, "Failed to create a window.\n");
1097 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1098 ok(!!d3d, "Failed to create a D3D object.\n");
1100 if (!(device = create_device(d3d, window, NULL)))
1102 skip("Failed to create a 3D device, skipping test.\n");
1103 goto cleanup;
1106 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1107 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels));
1108 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1109 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, 0, FALSE, &rt, NULL);
1110 if (available)
1112 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1113 IDirect3DSurface9_Release(rt);
1114 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1115 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, quality_levels, FALSE, &rt, NULL);
1116 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1118 else
1120 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1123 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1124 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels));
1125 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1126 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &rt, NULL);
1127 if (available)
1129 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1130 IDirect3DSurface9_Release(rt);
1131 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1132 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels, FALSE, &rt, NULL);
1133 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1135 else
1137 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1140 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1141 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1142 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1143 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1144 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1145 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, 0, FALSE, &rt, NULL);
1146 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1148 refcount = IDirect3DDevice9_Release(device);
1149 ok(!refcount, "Device has %u references left.\n", refcount);
1150 cleanup:
1151 IDirect3D9_Release(d3d);
1152 DestroyWindow(window);
1155 static void test_swapchain(void)
1157 IDirect3DSwapChain9 *swapchain0;
1158 IDirect3DSwapChain9 *swapchain1;
1159 IDirect3DSwapChain9 *swapchain2;
1160 IDirect3DSwapChain9 *swapchain3;
1161 IDirect3DSwapChain9 *swapchainX;
1162 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1163 D3DPRESENT_PARAMETERS d3dpp;
1164 IDirect3DDevice9 *device;
1165 IDirect3D9 *d3d;
1166 ULONG refcount;
1167 HWND window, window2;
1168 HRESULT hr;
1169 struct device_desc device_desc;
1171 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1172 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1173 ok(!!window, "Failed to create a window.\n");
1174 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1175 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1176 ok(!!window2, "Failed to create a window.\n");
1177 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1178 ok(!!d3d, "Failed to create a D3D object.\n");
1179 if (!(device = create_device(d3d, window, NULL)))
1181 skip("Failed to create a 3D device, skipping test.\n");
1182 goto cleanup;
1185 /* Get the implicit swapchain */
1186 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1187 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1188 /* Check if the back buffer count was modified */
1189 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1190 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1191 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1192 IDirect3DSwapChain9_Release(swapchain0);
1194 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1195 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1196 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1197 backbuffer = (void *)0xdeadbeef;
1198 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1199 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1200 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1201 backbuffer = (void *)0xdeadbeef;
1202 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1203 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1204 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1206 /* Check if there is a back buffer */
1207 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1208 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1209 ok(backbuffer != NULL, "The back buffer is NULL\n");
1210 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1212 /* The back buffer type value is ignored. */
1213 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1214 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1215 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1216 IDirect3DSurface9_Release(stereo_buffer);
1217 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1218 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1219 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1220 IDirect3DSurface9_Release(stereo_buffer);
1221 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1222 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1223 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1224 IDirect3DSurface9_Release(stereo_buffer);
1226 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1227 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1228 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1229 IDirect3DSurface9_Release(stereo_buffer);
1230 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1231 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1232 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1233 IDirect3DSurface9_Release(stereo_buffer);
1234 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1235 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1236 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1237 IDirect3DSurface9_Release(stereo_buffer);
1239 /* Try to get a nonexistent swapchain */
1240 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1241 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1242 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1243 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1245 /* Create a bunch of swapchains */
1246 d3dpp.BackBufferCount = 0;
1247 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1248 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1249 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1251 d3dpp.BackBufferCount = 1;
1252 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1253 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1255 d3dpp.BackBufferCount = 2;
1256 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1257 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1258 if(SUCCEEDED(hr)) {
1259 /* Swapchain 3, created with backbuffercount 2 */
1260 backbuffer = (void *) 0xdeadbeef;
1261 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1262 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1263 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1264 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1266 backbuffer = (void *) 0xdeadbeef;
1267 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1268 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1269 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1270 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1272 backbuffer = (void *) 0xdeadbeef;
1273 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1274 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1275 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1276 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1278 backbuffer = (void *) 0xdeadbeef;
1279 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1280 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1281 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1282 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1285 /* Check the back buffers of the swapchains */
1286 /* Swapchain 1, created with backbuffercount 0 */
1287 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1288 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1289 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1290 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1292 backbuffer = (void *) 0xdeadbeef;
1293 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1294 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1295 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1296 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1298 /* Swapchain 2 - created with backbuffercount 1 */
1299 backbuffer = (void *) 0xdeadbeef;
1300 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1301 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1302 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1303 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1305 backbuffer = (void *) 0xdeadbeef;
1306 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1307 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1308 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1309 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1311 backbuffer = (void *) 0xdeadbeef;
1312 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1313 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1314 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1315 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1317 /* Try getSwapChain on a manually created swapchain
1318 * it should fail, apparently GetSwapChain only returns implicit swapchains
1320 swapchainX = (void *) 0xdeadbeef;
1321 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1322 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1323 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1324 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1326 IDirect3DSwapChain9_Release(swapchain3);
1327 IDirect3DSwapChain9_Release(swapchain2);
1328 IDirect3DSwapChain9_Release(swapchain1);
1330 d3dpp.Windowed = FALSE;
1331 d3dpp.hDeviceWindow = window;
1332 d3dpp.BackBufferCount = 1;
1333 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1334 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1335 d3dpp.hDeviceWindow = window2;
1336 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1337 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1339 device_desc.width = registry_mode.dmPelsWidth;
1340 device_desc.height = registry_mode.dmPelsHeight;
1341 device_desc.device_window = window;
1342 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1343 hr = reset_device(device, &device_desc);
1344 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1346 d3dpp.hDeviceWindow = window;
1347 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1348 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1349 d3dpp.hDeviceWindow = window2;
1350 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1351 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1352 d3dpp.Windowed = TRUE;
1353 d3dpp.hDeviceWindow = window;
1354 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1355 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1356 d3dpp.hDeviceWindow = window2;
1357 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1358 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1360 refcount = IDirect3DDevice9_Release(device);
1361 ok(!refcount, "Device has %u references left.\n", refcount);
1362 cleanup:
1363 IDirect3D9_Release(d3d);
1364 DestroyWindow(window2);
1365 DestroyWindow(window);
1368 static void test_refcount(void)
1370 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1371 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1372 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1373 IDirect3DVertexShader9 *pVertexShader = NULL;
1374 IDirect3DPixelShader9 *pPixelShader = NULL;
1375 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1376 IDirect3DTexture9 *pTexture = NULL;
1377 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1378 IDirect3DVolume9 *pVolumeLevel = NULL;
1379 IDirect3DSurface9 *pStencilSurface = NULL;
1380 IDirect3DSurface9 *pOffscreenSurface = NULL;
1381 IDirect3DSurface9 *pRenderTarget = NULL;
1382 IDirect3DSurface9 *pRenderTarget2 = NULL;
1383 IDirect3DSurface9 *pRenderTarget3 = NULL;
1384 IDirect3DSurface9 *pTextureLevel = NULL;
1385 IDirect3DSurface9 *pBackBuffer = NULL;
1386 IDirect3DStateBlock9 *pStateBlock = NULL;
1387 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1388 IDirect3DSwapChain9 *pSwapChain = NULL;
1389 IDirect3DQuery9 *pQuery = NULL;
1390 D3DPRESENT_PARAMETERS d3dpp;
1391 IDirect3DDevice9 *device;
1392 ULONG refcount = 0, tmp;
1393 IDirect3D9 *d3d, *d3d2;
1394 HWND window;
1395 HRESULT hr;
1397 D3DVERTEXELEMENT9 decl[] =
1399 D3DDECL_END()
1402 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1403 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1404 ok(!!window, "Failed to create a window.\n");
1405 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1406 ok(!!d3d, "Failed to create a D3D object.\n");
1408 CHECK_REFCOUNT(d3d, 1);
1410 if (!(device = create_device(d3d, window, NULL)))
1412 skip("Failed to create a 3D device, skipping test.\n");
1413 goto cleanup;
1416 refcount = get_refcount((IUnknown *)device);
1417 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1419 CHECK_REFCOUNT(d3d, 2);
1421 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1422 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1424 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1425 CHECK_REFCOUNT(d3d, 3);
1426 CHECK_RELEASE_REFCOUNT(d3d, 2);
1429 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1430 * - the container is the device OR swapchain
1431 * - they hold a reference to the device
1432 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1433 * - they are not freed if refcount reaches 0.
1434 * - the refcount is not forwarded to the container.
1436 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1437 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1438 if (pSwapChain)
1440 CHECK_REFCOUNT( pSwapChain, 1);
1442 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1443 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1444 CHECK_REFCOUNT( pSwapChain, 1);
1445 if(pRenderTarget)
1447 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1448 CHECK_REFCOUNT( pRenderTarget, 1);
1450 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1451 CHECK_REFCOUNT(device, refcount);
1452 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1453 CHECK_REFCOUNT(device, refcount);
1455 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1456 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1457 CHECK_REFCOUNT( pRenderTarget, 2);
1458 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
1459 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
1460 CHECK_REFCOUNT(device, --refcount);
1462 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1463 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1464 CHECK_REFCOUNT(device, ++refcount);
1465 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1466 CHECK_REFCOUNT(device, --refcount);
1469 /* Render target and back buffer are identical. */
1470 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1471 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1472 if(pBackBuffer)
1474 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1475 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1476 pRenderTarget, pBackBuffer);
1477 pBackBuffer = NULL;
1479 CHECK_REFCOUNT(device, --refcount);
1481 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1482 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1483 CHECK_REFCOUNT( pSwapChain, 1);
1484 if(pStencilSurface)
1486 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1487 CHECK_REFCOUNT( pStencilSurface, 1);
1489 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1490 CHECK_REFCOUNT(device, refcount);
1491 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1492 CHECK_REFCOUNT(device, refcount);
1494 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
1495 CHECK_REFCOUNT(device, --refcount);
1497 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1498 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1499 CHECK_REFCOUNT(device, ++refcount);
1500 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1501 CHECK_REFCOUNT(device, --refcount);
1502 pStencilSurface = NULL;
1505 CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
1506 CHECK_REFCOUNT(device, --refcount);
1508 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1509 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1510 CHECK_REFCOUNT(device, ++refcount);
1511 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1512 CHECK_REFCOUNT(device, --refcount);
1513 pSwapChain = NULL;
1516 /* Buffers */
1517 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1518 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1519 if(pIndexBuffer)
1521 tmp = get_refcount( (IUnknown *)pIndexBuffer );
1523 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1524 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1525 hr = IDirect3DDevice9_SetIndices(device, NULL);
1526 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1529 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1530 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1531 if(pVertexBuffer)
1533 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1534 UINT offset = ~0;
1535 UINT stride = ~0;
1537 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1539 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1540 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1541 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1542 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1544 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1545 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1546 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1547 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1548 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1550 /* Shaders */
1551 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1552 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1553 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1554 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1555 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1556 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1557 /* Textures */
1558 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1559 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1560 if (pTexture)
1562 tmp = get_refcount( (IUnknown *)pTexture );
1564 /* SetTexture should not increase refcounts */
1565 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1566 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1567 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1568 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1570 /* This should not increment device refcount */
1571 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1572 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1573 /* But should increment texture's refcount */
1574 CHECK_REFCOUNT( pTexture, tmp+1 );
1575 /* Because the texture and surface refcount are identical */
1576 if (pTextureLevel)
1578 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1579 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1580 CHECK_REFCOUNT ( pTexture , tmp+2 );
1581 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1582 CHECK_REFCOUNT ( pTexture , tmp+1 );
1583 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1584 CHECK_REFCOUNT ( pTextureLevel, tmp );
1587 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1588 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1589 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1590 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1591 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1592 if (pVolumeTexture)
1594 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1596 /* This should not increment device refcount */
1597 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1598 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1599 /* But should increment volume texture's refcount */
1600 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1601 /* Because the volume texture and volume refcount are identical */
1602 if (pVolumeLevel)
1604 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1605 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1606 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1607 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1608 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1609 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1610 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1613 /* Surfaces */
1614 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1615 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1616 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1617 CHECK_REFCOUNT( pStencilSurface, 1 );
1618 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1619 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1620 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1621 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1622 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1623 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1624 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1625 CHECK_REFCOUNT( pRenderTarget3, 1 );
1626 /* Misc */
1627 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1628 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1630 memset(&d3dpp, 0, sizeof(d3dpp));
1631 d3dpp.Windowed = TRUE;
1632 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1633 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1634 d3dpp.EnableAutoDepthStencil = TRUE;
1635 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1636 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1637 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1638 if(pSwapChain)
1640 /* check implicit back buffer */
1641 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1642 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1643 CHECK_REFCOUNT( pSwapChain, 1);
1644 if(pBackBuffer)
1646 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1647 CHECK_REFCOUNT( pBackBuffer, 1);
1648 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
1649 CHECK_REFCOUNT(device, --refcount);
1651 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1652 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1653 CHECK_REFCOUNT(device, ++refcount);
1654 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1655 CHECK_REFCOUNT(device, --refcount);
1656 pBackBuffer = NULL;
1658 CHECK_REFCOUNT( pSwapChain, 1);
1660 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1661 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1663 hr = IDirect3DDevice9_BeginStateBlock(device);
1664 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1665 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1666 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1668 /* The implicit render target is not freed if refcount reaches 0.
1669 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1670 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1671 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1672 if(pRenderTarget2)
1674 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1675 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1676 pRenderTarget, pRenderTarget2);
1677 CHECK_REFCOUNT(device, --refcount);
1678 pRenderTarget2 = NULL;
1680 pRenderTarget = NULL;
1682 cleanup:
1683 CHECK_RELEASE(device, device, --refcount);
1685 /* Buffers */
1686 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1687 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1688 /* Shaders */
1689 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1690 CHECK_RELEASE(pVertexShader, device, --refcount);
1691 CHECK_RELEASE(pPixelShader, device, --refcount);
1692 /* Textures */
1693 CHECK_RELEASE(pTextureLevel, device, --refcount);
1694 CHECK_RELEASE(pCubeTexture, device, --refcount);
1695 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1696 /* Surfaces */
1697 CHECK_RELEASE(pStencilSurface, device, --refcount);
1698 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1699 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1700 /* Misc */
1701 CHECK_RELEASE(pStateBlock, device, --refcount);
1702 CHECK_RELEASE(pSwapChain, device, --refcount);
1703 CHECK_RELEASE(pQuery, device, --refcount);
1704 /* This will destroy device - cannot check the refcount here */
1705 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1706 CHECK_RELEASE_REFCOUNT(d3d, 0);
1707 DestroyWindow(window);
1710 static void test_cursor(void)
1712 IDirect3DSurface9 *cursor = NULL;
1713 IDirect3DDevice9 *device;
1714 CURSORINFO info;
1715 IDirect3D9 *d3d;
1716 ULONG refcount;
1717 HCURSOR cur;
1718 HWND window;
1719 HRESULT hr;
1720 BOOL ret;
1722 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1723 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1724 ok(!!window, "Failed to create a window.\n");
1726 ret = SetCursorPos(50, 50);
1727 ok(ret, "Failed to set cursor position.\n");
1728 flush_events();
1729 memset(&info, 0, sizeof(info));
1730 info.cbSize = sizeof(info);
1731 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1732 cur = info.hCursor;
1734 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1735 ok(!!d3d, "Failed to create a D3D object.\n");
1736 if (!(device = create_device(d3d, window, NULL)))
1738 skip("Failed to create a 3D device, skipping test.\n");
1739 goto cleanup;
1742 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1743 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1744 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1746 /* Initially hidden */
1747 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1748 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1750 /* Not enabled without a surface*/
1751 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1752 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1754 /* Fails */
1755 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1756 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1758 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1759 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1761 IDirect3DSurface9_Release(cursor);
1763 memset(&info, 0, sizeof(info));
1764 info.cbSize = sizeof(info);
1765 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1766 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1767 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1769 /* Still hidden */
1770 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1771 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1773 /* Enabled now*/
1774 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1775 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1777 memset(&info, 0, sizeof(info));
1778 info.cbSize = sizeof(info);
1779 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1780 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1781 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1783 refcount = IDirect3DDevice9_Release(device);
1784 ok(!refcount, "Device has %u references left.\n", refcount);
1785 cleanup:
1786 IDirect3D9_Release(d3d);
1787 DestroyWindow(window);
1790 static void test_reset(void)
1792 HRESULT hr;
1793 RECT winrect;
1794 D3DPRESENT_PARAMETERS d3dpp;
1795 D3DDISPLAYMODE d3ddm, d3ddm2;
1796 D3DVIEWPORT9 vp;
1797 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1798 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1799 IDirect3DSurface9 *surface;
1800 IDirect3DTexture9 *texture;
1801 IDirect3DVertexShader9 *shader;
1802 UINT i, adapter_mode_count;
1803 D3DLOCKED_RECT lockrect;
1804 IDirect3DDevice9 *device1 = NULL;
1805 IDirect3DDevice9 *device2 = NULL;
1806 IDirect3DSwapChain9 *swapchain;
1807 struct device_desc device_desc;
1808 DEVMODEW devmode;
1809 IDirect3D9 *d3d;
1810 D3DCAPS9 caps;
1811 DWORD value;
1812 HWND hwnd;
1813 LONG ret;
1814 struct
1816 UINT w;
1817 UINT h;
1818 } *modes = NULL;
1819 UINT mode_count = 0;
1821 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1822 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1823 ok(!!hwnd, "Failed to create a window.\n");
1824 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1825 ok(!!d3d, "Failed to create a D3D object.\n");
1827 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1828 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1829 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1830 for(i = 0; i < adapter_mode_count; ++i)
1832 UINT j;
1833 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1834 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1835 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1837 for (j = 0; j < mode_count; ++j)
1839 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1840 break;
1842 if (j == mode_count)
1844 modes[j].w = d3ddm2.Width;
1845 modes[j].h = d3ddm2.Height;
1846 ++mode_count;
1849 /* We use them as invalid modes */
1850 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1851 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1852 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1853 d3ddm2.Width, d3ddm2.Height);
1854 goto cleanup;
1858 if (mode_count < 2)
1860 skip("Less than 2 modes supported, skipping mode tests\n");
1861 goto cleanup;
1864 i = 0;
1865 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1867 device_desc.width = modes[i].w;
1868 device_desc.height = modes[i].h;
1869 device_desc.device_window = hwnd;
1870 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1871 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1873 skip("Failed to create a D3D device, skipping tests.\n");
1874 goto cleanup;
1876 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1877 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1879 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1880 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1882 width = GetSystemMetrics(SM_CXSCREEN);
1883 height = GetSystemMetrics(SM_CYSCREEN);
1884 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1885 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1887 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1888 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1889 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1890 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1891 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1892 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1893 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1894 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1896 i = 1;
1897 vp.X = 10;
1898 vp.Y = 20;
1899 vp.MinZ = 2;
1900 vp.MaxZ = 3;
1901 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1902 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1904 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1905 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1906 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1907 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1908 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1910 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1911 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1912 d3dpp.Windowed = FALSE;
1913 d3dpp.BackBufferWidth = modes[i].w;
1914 d3dpp.BackBufferHeight = modes[i].h;
1915 d3dpp.BackBufferFormat = d3ddm.Format;
1916 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1917 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1918 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1919 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1921 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1922 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1923 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1925 ZeroMemory(&vp, sizeof(vp));
1926 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1927 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1928 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1929 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1930 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1931 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1932 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1933 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1935 width = GetSystemMetrics(SM_CXSCREEN);
1936 height = GetSystemMetrics(SM_CYSCREEN);
1937 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1938 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1940 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1941 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1942 memset(&d3dpp, 0, sizeof(d3dpp));
1943 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1944 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1945 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1946 d3dpp.BackBufferWidth, modes[i].w);
1947 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1948 d3dpp.BackBufferHeight, modes[i].h);
1949 IDirect3DSwapChain9_Release(swapchain);
1951 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1952 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1953 d3dpp.Windowed = TRUE;
1954 d3dpp.BackBufferWidth = 400;
1955 d3dpp.BackBufferHeight = 300;
1956 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1957 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1958 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1959 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1960 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1962 width = GetSystemMetrics(SM_CXSCREEN);
1963 height = GetSystemMetrics(SM_CYSCREEN);
1964 ok(width == orig_width, "Screen width is %d\n", width);
1965 ok(height == orig_height, "Screen height is %d\n", height);
1967 ZeroMemory(&vp, sizeof(vp));
1968 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1969 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1970 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1971 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1972 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1973 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1974 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1975 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1977 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1978 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1979 memset(&d3dpp, 0, sizeof(d3dpp));
1980 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1981 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1982 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1983 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1984 IDirect3DSwapChain9_Release(swapchain);
1986 memset(&devmode, 0, sizeof(devmode));
1987 devmode.dmSize = sizeof(devmode);
1988 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1989 devmode.dmPelsWidth = modes[1].w;
1990 devmode.dmPelsHeight = modes[1].h;
1991 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1992 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1993 width = GetSystemMetrics(SM_CXSCREEN);
1994 height = GetSystemMetrics(SM_CYSCREEN);
1995 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1996 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1998 d3dpp.BackBufferWidth = 500;
1999 d3dpp.BackBufferHeight = 400;
2000 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
2001 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2002 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed, hr %#x.\n", hr);
2003 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2004 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x.\n", hr);
2006 width = GetSystemMetrics(SM_CXSCREEN);
2007 height = GetSystemMetrics(SM_CYSCREEN);
2008 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2009 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2011 ZeroMemory(&vp, sizeof(vp));
2012 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2013 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed, hr %#x.\n", hr);
2014 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
2015 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
2016 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
2017 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
2018 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
2019 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
2021 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2022 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2023 memset(&d3dpp, 0, sizeof(d3dpp));
2024 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2025 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2026 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2027 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2028 IDirect3DSwapChain9_Release(swapchain);
2030 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2031 devmode.dmPelsWidth = orig_width;
2032 devmode.dmPelsHeight = orig_height;
2033 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2034 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2035 width = GetSystemMetrics(SM_CXSCREEN);
2036 height = GetSystemMetrics(SM_CYSCREEN);
2037 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
2038 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
2040 SetRect(&winrect, 0, 0, 200, 150);
2041 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
2042 ok(SetWindowPos(hwnd, NULL, 0, 0,
2043 winrect.right-winrect.left,
2044 winrect.bottom-winrect.top,
2045 SWP_NOMOVE|SWP_NOZORDER),
2046 "SetWindowPos failed\n");
2048 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2049 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2050 d3dpp.Windowed = TRUE;
2051 d3dpp.BackBufferWidth = 0;
2052 d3dpp.BackBufferHeight = 0;
2053 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
2054 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2055 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2056 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2057 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2059 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2060 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2061 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2062 d3dpp.BackBufferFormat, d3ddm.Format);
2063 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2064 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2065 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2066 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2067 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
2068 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2069 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2070 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2071 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2072 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2073 d3dpp.FullScreen_RefreshRateInHz);
2074 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2076 ZeroMemory(&vp, sizeof(vp));
2077 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2078 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
2079 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
2080 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
2081 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
2082 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
2083 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2084 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2086 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2087 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2088 memset(&d3dpp, 0, sizeof(d3dpp));
2089 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2090 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2091 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2092 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2093 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2094 d3dpp.BackBufferFormat, d3ddm.Format);
2095 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2096 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2097 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2098 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2099 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
2100 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2101 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2102 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2103 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2104 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2105 d3dpp.FullScreen_RefreshRateInHz);
2106 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2107 IDirect3DSwapChain9_Release(swapchain);
2109 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2110 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2111 d3dpp.Windowed = TRUE;
2112 d3dpp.BackBufferWidth = 400;
2113 d3dpp.BackBufferHeight = 300;
2115 /* _Reset fails if there is a resource in the default pool */
2116 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
2117 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2118 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2119 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2120 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2121 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2122 IDirect3DSurface9_Release(surface);
2123 /* Reset again to get the device out of the lost state */
2124 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2125 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2126 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2127 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2129 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
2131 IDirect3DVolumeTexture9 *volume_texture;
2133 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
2134 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
2135 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
2136 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2137 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2138 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2139 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
2140 hr, D3DERR_DEVICENOTRESET);
2141 IDirect3DVolumeTexture9_Release(volume_texture);
2142 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2143 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
2144 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2145 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2147 else
2149 skip("Volume textures not supported.\n");
2152 /* Scratch, sysmem and managed pools are fine */
2153 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2154 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2155 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2156 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2157 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2158 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2159 IDirect3DSurface9_Release(surface);
2161 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2162 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2163 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2164 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2165 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2166 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2167 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2168 IDirect3DSurface9_Release(surface);
2170 /* The depth stencil should get reset to the auto depth stencil when present. */
2171 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2172 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2174 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2175 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2176 ok(surface == NULL, "Depth stencil should be NULL\n");
2178 d3dpp.EnableAutoDepthStencil = TRUE;
2179 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2180 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2181 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2183 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2184 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2185 ok(surface != NULL, "Depth stencil should not be NULL\n");
2186 if (surface) IDirect3DSurface9_Release(surface);
2188 d3dpp.EnableAutoDepthStencil = FALSE;
2189 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2190 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2192 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2193 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2194 ok(surface == NULL, "Depth stencil should be NULL\n");
2196 /* Will a sysmem or scratch survive while locked */
2197 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2198 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2199 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2200 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2201 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2202 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2203 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2204 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2205 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2206 IDirect3DSurface9_UnlockRect(surface);
2207 IDirect3DSurface9_Release(surface);
2209 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2210 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2211 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2212 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2213 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2214 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2215 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2216 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2217 IDirect3DSurface9_UnlockRect(surface);
2218 IDirect3DSurface9_Release(surface);
2220 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2221 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2222 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2223 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2224 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2225 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2226 IDirect3DTexture9_Release(texture);
2228 /* A reference held to an implicit surface causes failures as well */
2229 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2230 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2231 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2232 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2233 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2234 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2235 IDirect3DSurface9_Release(surface);
2236 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2237 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2238 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2239 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2241 /* Shaders are fine as well */
2242 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2243 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2244 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2245 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2246 IDirect3DVertexShader9_Release(shader);
2248 /* Try setting invalid modes */
2249 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2250 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2251 d3dpp.Windowed = FALSE;
2252 d3dpp.BackBufferWidth = 32;
2253 d3dpp.BackBufferHeight = 32;
2254 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2255 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2256 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2257 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2259 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2260 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2261 d3dpp.Windowed = FALSE;
2262 d3dpp.BackBufferWidth = 801;
2263 d3dpp.BackBufferHeight = 600;
2264 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2265 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2266 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2267 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2269 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2270 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2271 d3dpp.Windowed = FALSE;
2272 d3dpp.BackBufferWidth = 0;
2273 d3dpp.BackBufferHeight = 0;
2274 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2275 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2276 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2277 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2279 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2281 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2282 d3dpp.Windowed = TRUE;
2283 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2284 d3dpp.BackBufferFormat = d3ddm.Format;
2285 d3dpp.EnableAutoDepthStencil = FALSE;
2286 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2288 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2289 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2291 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2292 goto cleanup;
2295 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2296 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2298 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2299 d3dpp.Windowed = TRUE;
2300 d3dpp.BackBufferWidth = 400;
2301 d3dpp.BackBufferHeight = 300;
2302 d3dpp.EnableAutoDepthStencil = TRUE;
2303 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2305 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2306 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2308 if (FAILED(hr)) goto cleanup;
2310 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2311 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2312 ok(surface != NULL, "Depth stencil should not be NULL\n");
2313 if (surface) IDirect3DSurface9_Release(surface);
2315 cleanup:
2316 HeapFree(GetProcessHeap(), 0, modes);
2317 if (device2)
2319 UINT refcount = IDirect3DDevice9_Release(device2);
2320 ok(!refcount, "Device has %u references left.\n", refcount);
2322 if (device1)
2324 UINT refcount = IDirect3DDevice9_Release(device1);
2325 ok(!refcount, "Device has %u references left.\n", refcount);
2327 IDirect3D9_Release(d3d);
2328 DestroyWindow(hwnd);
2331 /* Test adapter display modes */
2332 static void test_display_modes(void)
2334 D3DDISPLAYMODE dmode;
2335 IDirect3D9 *d3d;
2337 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2338 ok(!!d3d, "Failed to create a D3D object.\n");
2340 #define TEST_FMT(x,r) do { \
2341 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2342 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2343 } while(0)
2345 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2346 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2347 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2348 /* D3DFMT_R5G6B5 */
2349 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2350 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2351 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2352 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2353 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2354 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2355 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2356 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2357 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2358 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2359 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2360 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2362 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2363 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2365 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2366 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2367 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2369 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2370 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2371 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2372 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2373 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2374 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2376 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2377 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2378 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2379 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2380 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2381 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2382 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2383 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2384 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2385 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2387 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2388 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2389 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2390 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2391 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2392 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2393 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2394 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2395 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2396 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2398 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2399 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2400 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2401 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2402 /* Floating point formats */
2403 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2404 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2405 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2407 /* IEEE formats */
2408 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2409 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2410 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2412 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2414 TEST_FMT(0, D3DERR_INVALIDCALL);
2416 IDirect3D9_Release(d3d);
2419 static void test_scene(void)
2421 IDirect3DSurface9 *surface1, *surface2, *surface3;
2422 IDirect3DSurface9 *backBuffer, *rt, *ds;
2423 RECT rect = {0, 0, 128, 128};
2424 IDirect3DDevice9 *device;
2425 IDirect3D9 *d3d;
2426 ULONG refcount;
2427 D3DCAPS9 caps;
2428 HWND window;
2429 HRESULT hr;
2431 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2432 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2433 ok(!!window, "Failed to create a window.\n");
2434 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2435 ok(!!d3d, "Failed to create a D3D object.\n");
2436 if (!(device = create_device(d3d, window, NULL)))
2438 skip("Failed to create a 3D device, skipping test.\n");
2439 goto cleanup;
2442 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2443 memset(&caps, 0, sizeof(caps));
2444 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2445 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2447 /* Test an EndScene without BeginScene. Should return an error */
2448 hr = IDirect3DDevice9_EndScene(device);
2449 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2451 /* Test a normal BeginScene / EndScene pair, this should work */
2452 hr = IDirect3DDevice9_BeginScene(device);
2453 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2454 hr = IDirect3DDevice9_EndScene(device);
2455 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2457 /* Test another EndScene without having begun a new scene. Should return an error */
2458 hr = IDirect3DDevice9_EndScene(device);
2459 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2461 /* Two nested BeginScene and EndScene calls */
2462 hr = IDirect3DDevice9_BeginScene(device);
2463 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2464 hr = IDirect3DDevice9_BeginScene(device);
2465 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2466 hr = IDirect3DDevice9_EndScene(device);
2467 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2468 hr = IDirect3DDevice9_EndScene(device);
2469 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2471 /* Create some surfaces to test stretchrect between the scenes */
2472 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2473 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2474 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2475 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2476 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2477 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2478 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2479 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2480 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2481 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2482 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2483 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2485 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2486 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2487 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2488 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2490 /* First make sure a simple StretchRect call works */
2491 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2492 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2493 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2494 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2495 if (0) /* Disabled for now because it crashes in wine */
2497 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2498 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2499 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2502 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2503 * BeginScene - Endscene pair with normal surfaces and render targets, but
2504 * not depth stencil surfaces. */
2505 hr = IDirect3DDevice9_BeginScene(device);
2506 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2508 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2509 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2510 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2511 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2512 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2513 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2514 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2516 hr = IDirect3DDevice9_EndScene(device);
2517 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2519 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2520 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2521 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2523 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2524 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2525 hr = IDirect3DDevice9_BeginScene(device);
2526 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2527 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2528 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2529 hr = IDirect3DDevice9_EndScene(device);
2530 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2532 IDirect3DSurface9_Release(rt);
2533 IDirect3DSurface9_Release(ds);
2534 IDirect3DSurface9_Release(backBuffer);
2535 IDirect3DSurface9_Release(surface1);
2536 IDirect3DSurface9_Release(surface2);
2537 IDirect3DSurface9_Release(surface3);
2538 refcount = IDirect3DDevice9_Release(device);
2539 ok(!refcount, "Device has %u references left.\n", refcount);
2540 cleanup:
2541 IDirect3D9_Release(d3d);
2542 DestroyWindow(window);
2545 static void test_limits(void)
2547 IDirect3DTexture9 *texture;
2548 IDirect3DDevice9 *device;
2549 IDirect3D9 *d3d;
2550 unsigned int i;
2551 ULONG refcount;
2552 HWND window;
2553 HRESULT hr;
2555 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2556 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2557 ok(!!window, "Failed to create a window.\n");
2558 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2559 ok(!!d3d, "Failed to create a D3D object.\n");
2560 if (!(device = create_device(d3d, window, NULL)))
2562 skip("Failed to create a 3D device, skipping test.\n");
2563 goto cleanup;
2566 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2567 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2569 /* There are 16 pixel samplers. We should be able to access all of them */
2570 for (i = 0; i < 16; ++i)
2572 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2573 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2574 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2575 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2576 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2577 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2580 /* Now test all 8 textures stage states */
2581 for (i = 0; i < 8; ++i)
2583 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2584 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2587 /* Investigations show that accessing higher samplers / textures stage
2588 * states does not return an error either. Writing to too high samplers
2589 * (approximately sampler 40) causes memory corruption in Windows, so
2590 * there is no bounds checking. */
2591 IDirect3DTexture9_Release(texture);
2592 refcount = IDirect3D9_Release(device);
2593 ok(!refcount, "Device has %u references left.\n", refcount);
2594 cleanup:
2595 IDirect3D9_Release(d3d);
2596 DestroyWindow(window);
2599 static void test_depthstenciltest(void)
2601 HRESULT hr;
2602 IDirect3DDevice9 *pDevice = NULL;
2603 D3DPRESENT_PARAMETERS d3dpp;
2604 D3DDISPLAYMODE d3ddm;
2605 IDirect3DSurface9 *pDepthStencil = NULL;
2606 IDirect3DSurface9 *pDepthStencil2 = NULL;
2607 IDirect3D9 *d3d;
2608 DWORD state;
2609 HWND hwnd;
2611 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2612 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2613 ok(!!hwnd, "Failed to create a window.\n");
2614 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2615 ok(!!d3d, "Failed to create a D3D object.\n");
2617 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2618 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2619 d3dpp.Windowed = TRUE;
2620 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2621 d3dpp.BackBufferWidth = 800;
2622 d3dpp.BackBufferHeight = 600;
2623 d3dpp.BackBufferFormat = d3ddm.Format;
2624 d3dpp.EnableAutoDepthStencil = TRUE;
2625 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2627 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2628 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2629 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2630 if(!pDevice)
2632 skip("Failed to create a d3d device\n");
2633 goto cleanup;
2636 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2637 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2639 /* Try to clear */
2640 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2641 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2643 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2644 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2646 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2647 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2648 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2649 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2651 /* This left the render states untouched! */
2652 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2653 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2654 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2655 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2656 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2657 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2658 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2659 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2660 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2661 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2662 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2663 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2665 /* This is supposed to fail now */
2666 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2667 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2669 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2670 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2672 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2673 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2675 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2676 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2677 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2679 /* Now it works again */
2680 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2681 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2683 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2684 if(pDevice) IDirect3D9_Release(pDevice);
2686 /* Now see if autodepthstencil disable is honored. First, without a format set */
2687 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2688 d3dpp.Windowed = TRUE;
2689 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2690 d3dpp.BackBufferWidth = 800;
2691 d3dpp.BackBufferHeight = 600;
2692 d3dpp.BackBufferFormat = d3ddm.Format;
2693 d3dpp.EnableAutoDepthStencil = FALSE;
2694 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2696 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2697 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2698 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2699 if(!pDevice)
2701 skip("Failed to create a d3d device\n");
2702 goto cleanup;
2705 pDepthStencil = NULL;
2706 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2707 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2708 if(pDepthStencil) {
2709 IDirect3DSurface9_Release(pDepthStencil);
2710 pDepthStencil = NULL;
2713 /* Check the depth test state */
2714 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2715 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2716 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2718 if(pDevice) IDirect3D9_Release(pDevice);
2720 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2721 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2722 d3dpp.Windowed = TRUE;
2723 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2724 d3dpp.BackBufferWidth = 800;
2725 d3dpp.BackBufferHeight = 600;
2726 d3dpp.BackBufferFormat = d3ddm.Format;
2727 d3dpp.EnableAutoDepthStencil = FALSE;
2728 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2730 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2731 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2732 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2733 if(!pDevice)
2735 skip("Failed to create a d3d device\n");
2736 goto cleanup;
2739 pDepthStencil = NULL;
2740 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2741 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2742 if(pDepthStencil) {
2743 IDirect3DSurface9_Release(pDepthStencil);
2744 pDepthStencil = NULL;
2747 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2748 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2749 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2751 cleanup:
2752 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2753 if (pDevice)
2755 UINT refcount = IDirect3D9_Release(pDevice);
2756 ok(!refcount, "Device has %u references left.\n", refcount);
2758 IDirect3D9_Release(d3d);
2759 DestroyWindow(hwnd);
2762 static void test_get_rt(void)
2764 IDirect3DSurface9 *backbuffer, *rt;
2765 IDirect3DDevice9 *device;
2766 IDirect3D9 *d3d9;
2767 D3DCAPS9 caps;
2768 HWND window;
2769 HRESULT hr;
2770 ULONG ref;
2771 UINT i;
2773 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2774 0, 0, 128, 128, 0, 0, 0, 0);
2775 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2776 ok(!!d3d9, "Failed to create a D3D object.\n");
2777 device = create_device(d3d9, window, NULL);
2778 if (!device)
2780 skip("Failed to create a D3D device, skipping tests.\n");
2781 goto done;
2784 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2785 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2786 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2788 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2789 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2791 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2793 rt = backbuffer;
2794 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2795 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2796 ok(!rt, "Got rt %p.\n", rt);
2799 IDirect3DSurface9_Release(backbuffer);
2801 ref = IDirect3DDevice9_Release(device);
2802 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2803 done:
2804 IDirect3D9_Release(d3d9);
2805 DestroyWindow(window);
2808 static void test_draw_primitive(void)
2810 static const struct
2812 float position[3];
2813 DWORD color;
2815 quad[] =
2817 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2818 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2819 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2820 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2822 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
2823 static const D3DVERTEXELEMENT9 decl_elements[] =
2825 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2826 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2827 D3DDECL_END()
2830 IDirect3DVertexDeclaration9 *vertex_declaration;
2831 IDirect3DVertexBuffer9 *vertex_buffer;
2832 IDirect3DIndexBuffer9 *index_buffer;
2833 IDirect3DDevice9 *device;
2834 IDirect3D9 *d3d9;
2835 ULONG refcount;
2836 HWND window;
2837 HRESULT hr;
2838 void *ptr;
2840 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
2841 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2842 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2843 ok(!!d3d9, "Failed to create a D3D object.\n");
2844 if (!(device = create_device(d3d9, window, NULL)))
2846 skip("Failed to create a D3D device.\n");
2847 IDirect3D9_Release(d3d9);
2848 DestroyWindow(window);
2849 return;
2852 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2853 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
2855 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
2856 D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2857 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#x.\n", hr);
2858 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2859 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2860 memcpy(ptr, quad, sizeof(quad));
2861 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2862 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2863 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2864 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#x.\n", hr);
2866 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
2867 D3DPOOL_DEFAULT, &index_buffer, NULL);
2868 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#x.\n", hr);
2869 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2870 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2871 memcpy(ptr, indices, sizeof(indices));
2872 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2873 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2875 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2876 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#x.\n", hr);
2878 hr = IDirect3DDevice9_BeginScene(device);
2879 ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2881 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2882 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2884 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2885 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2887 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2888 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2890 hr = IDirect3DDevice9_SetIndices(device, NULL);
2891 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2892 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2893 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2894 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2896 /* Valid index buffer, NULL vertex declaration. Should fail */
2897 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2898 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2899 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2900 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2901 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2903 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2904 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2905 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2907 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2908 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2910 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2911 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2913 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2914 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2916 /* NULL index buffer, valid vertex vertex declaration. Should succeed */
2917 hr = IDirect3DDevice9_SetIndices(device, NULL);
2918 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2919 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2920 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2921 todo_wine ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2923 /* Valid index buffer and vertex declaration. Should succeed */
2924 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2925 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2926 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2927 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2928 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2930 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2931 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2932 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#x.\n", hr);
2934 hr = IDirect3DDevice9_EndScene(device);
2935 ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2937 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2938 ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2940 IDirect3DVertexBuffer9_Release(vertex_buffer);
2941 IDirect3DIndexBuffer9_Release(index_buffer);
2942 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2943 refcount = IDirect3DDevice9_Release(device);
2944 ok(!refcount, "Device has %u references left.\n", refcount);
2945 IDirect3D9_Release(d3d9);
2946 DestroyWindow(window);
2949 static void test_null_stream(void)
2951 IDirect3DVertexBuffer9 *buffer = NULL;
2952 IDirect3DDevice9 *device;
2953 IDirect3D9 *d3d9;
2954 ULONG refcount;
2955 HWND window;
2956 HRESULT hr;
2957 IDirect3DVertexShader9 *shader = NULL;
2958 IDirect3DVertexDeclaration9 *decl = NULL;
2959 static const DWORD shader_code[] =
2961 0xfffe0101, /* vs_1_1 */
2962 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2963 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2964 0x0000ffff /* end */
2966 static const D3DVERTEXELEMENT9 decl_elements[] = {
2967 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2968 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2969 D3DDECL_END()
2972 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2973 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2974 ok(!!window, "Failed to create a window.\n");
2975 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2976 ok(!!d3d9, "Failed to create a D3D object.\n");
2977 if (!(device = create_device(d3d9, window, NULL)))
2979 skip("Failed to create a 3D device, skipping test.\n");
2980 goto cleanup;
2983 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2984 if(FAILED(hr)) {
2985 skip("No vertex shader support\n");
2986 goto cleanup;
2988 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2989 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2990 if (FAILED(hr)) {
2991 skip("Vertex declaration handling not possible.\n");
2992 goto cleanup;
2994 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2995 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2996 if (FAILED(hr)) {
2997 skip("Vertex buffer handling not possible.\n");
2998 goto cleanup;
3001 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
3002 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3003 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
3004 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3005 hr = IDirect3DDevice9_SetVertexShader(device, shader);
3006 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
3007 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3008 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
3010 hr = IDirect3DDevice9_BeginScene(device);
3011 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3012 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
3013 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3014 hr = IDirect3DDevice9_EndScene(device);
3015 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3017 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3018 IDirect3DDevice9_SetVertexShader(device, NULL);
3019 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3021 cleanup:
3022 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
3023 if (decl) IDirect3DVertexDeclaration9_Release(decl);
3024 if (shader) IDirect3DVertexShader9_Release(shader);
3025 if (device)
3027 refcount = IDirect3DDevice9_Release(device);
3028 ok(!refcount, "Device has %u references left.\n", refcount);
3030 IDirect3D9_Release(d3d9);
3031 DestroyWindow(window);
3034 static void test_lights(void)
3036 IDirect3DDevice9 *device;
3037 IDirect3D9 *d3d9;
3038 ULONG refcount;
3039 HWND window;
3040 HRESULT hr;
3041 unsigned int i;
3042 BOOL enabled;
3043 D3DCAPS9 caps;
3045 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3046 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3047 ok(!!window, "Failed to create a window.\n");
3048 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3049 ok(!!d3d9, "Failed to create a D3D object.\n");
3050 if (!(device = create_device(d3d9, window, NULL)))
3052 skip("Failed to create a 3D device, skipping test.\n");
3053 goto cleanup;
3056 memset(&caps, 0, sizeof(caps));
3057 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3058 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
3060 for(i = 1; i <= caps.MaxActiveLights; i++) {
3061 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
3062 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
3063 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
3064 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
3065 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
3068 /* TODO: Test the rendering results in this situation */
3069 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
3070 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
3071 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
3072 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
3073 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
3074 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
3075 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
3077 for(i = 1; i <= caps.MaxActiveLights; i++) {
3078 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
3079 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
3082 refcount = IDirect3DDevice9_Release(device);
3083 ok(!refcount, "Device has %u references left.\n", refcount);
3084 cleanup:
3085 IDirect3D9_Release(d3d9);
3086 DestroyWindow(window);
3089 static void test_set_stream_source(void)
3091 IDirect3DVertexBuffer9 *vb;
3092 IDirect3DDevice9 *device;
3093 IDirect3D9 *d3d9;
3094 ULONG refcount;
3095 HWND window;
3096 HRESULT hr;
3098 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3099 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3100 ok(!!window, "Failed to create a window.\n");
3101 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3102 ok(!!d3d9, "Failed to create a D3D object.\n");
3103 if (!(device = create_device(d3d9, window, NULL)))
3105 skip("Failed to create a 3D device, skipping test.\n");
3106 goto cleanup;
3109 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
3110 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
3112 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
3113 * (Radeon 9000 verified) reject them, so accept both results. Wine
3114 * currently rejects this to be able to optimize the vbo conversion, but
3115 * writes a WARN. */
3116 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
3117 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3118 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
3119 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3120 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
3121 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3122 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
3123 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3124 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
3125 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3127 /* Try to set the NULL buffer with an offset and stride 0 */
3128 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3129 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3130 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
3131 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3132 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
3133 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3134 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
3135 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3136 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
3137 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3139 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3140 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3142 IDirect3DVertexBuffer9_Release(vb);
3143 refcount = IDirect3DDevice9_Release(device);
3144 ok(!refcount, "Device has %u references left.\n", refcount);
3145 cleanup:
3146 IDirect3D9_Release(d3d9);
3147 DestroyWindow(window);
3150 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
3151 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
3152 * a fixed number of combinations are possible in fullscreen mode. In windowed
3153 * mode more combinations are allowed due to format conversion and this is
3154 * likely driver dependent. */
3155 static void test_display_formats(void)
3157 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
3158 unsigned int backbuffer, display;
3159 unsigned int windowed;
3160 IDirect3D9 *d3d9;
3161 BOOL should_pass;
3162 BOOL has_modes;
3163 HRESULT hr;
3165 static const struct
3167 const char *name;
3168 D3DFORMAT format;
3169 D3DFORMAT alpha_format;
3170 BOOL display;
3171 BOOL windowed;
3173 formats[] =
3175 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
3176 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
3177 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
3178 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
3179 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3180 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3181 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3184 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3185 ok(!!d3d9, "Failed to create a D3D object.\n");
3187 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
3189 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3191 for (windowed = 0; windowed <= 1; ++windowed)
3193 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
3195 should_pass = FALSE;
3197 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3199 D3DFORMAT backbuffer_format;
3201 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3202 backbuffer_format = formats[display].format;
3203 else
3204 backbuffer_format = formats[backbuffer].format;
3206 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3207 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3208 if (hr == D3D_OK)
3210 if (windowed)
3212 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3213 backbuffer_format, formats[display].format);
3214 should_pass = (hr == D3D_OK);
3216 else
3217 should_pass = (formats[display].format == formats[backbuffer].format
3218 || (formats[display].alpha_format
3219 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3223 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3224 formats[display].format, formats[backbuffer].format, windowed);
3225 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3226 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3227 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3232 IDirect3D9_Release(d3d9);
3235 static void test_scissor_size(void)
3237 struct device_desc device_desc;
3238 IDirect3D9 *d3d9_ptr;
3239 unsigned int i;
3240 static struct {
3241 int winx; int winy; int backx; int backy; DWORD flags;
3242 } scts[] = { /* scissor tests */
3243 {800, 600, 640, 480, 0},
3244 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3245 {640, 480, 800, 600, 0},
3246 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3249 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3250 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3252 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
3253 IDirect3DDevice9 *device_ptr = 0;
3254 HRESULT hr;
3255 HWND hwnd = 0;
3256 RECT scissorrect;
3258 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3259 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3261 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3263 scts[i].backx = registry_mode.dmPelsWidth;
3264 scts[i].backy = registry_mode.dmPelsHeight;
3267 device_desc.device_window = hwnd;
3268 device_desc.width = scts[i].backx;
3269 device_desc.height = scts[i].backy;
3270 device_desc.flags = scts[i].flags;
3271 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3273 skip("Failed to create a 3D device, skipping test.\n");
3274 DestroyWindow(hwnd);
3275 goto err_out;
3278 /* Check for the default scissor rect size */
3279 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3280 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3281 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3282 && scissorrect.top == 0 && scissorrect.left == 0,
3283 "Scissorrect mismatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3284 scts[i].backx, scts[i].backy);
3286 /* check the scissorrect values after a reset */
3287 device_desc.width = registry_mode.dmPelsWidth;
3288 device_desc.height = registry_mode.dmPelsHeight;
3289 device_desc.flags = scts[i].flags;
3290 hr = reset_device(device_ptr, &device_desc);
3291 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3292 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3293 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3295 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3296 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3297 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3298 && scissorrect.top == 0 && scissorrect.left == 0,
3299 "Scissorrect mismatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3300 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3302 if(device_ptr) {
3303 ULONG ref;
3305 ref = IDirect3DDevice9_Release(device_ptr);
3306 DestroyWindow(hwnd);
3307 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3311 err_out:
3312 IDirect3D9_Release(d3d9_ptr);
3315 static void test_multi_device(void)
3317 IDirect3DDevice9 *device1, *device2;
3318 HWND window1, window2;
3319 IDirect3D9 *d3d9;
3320 ULONG refcount;
3322 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3323 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3324 ok(!!window1, "Failed to create a window.\n");
3325 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3326 ok(!!d3d9, "Failed to create a D3D object.\n");
3327 if (!(device1 = create_device(d3d9, window1, NULL)))
3329 skip("Failed to create a 3D device, skipping test.\n");
3330 IDirect3D9_Release(d3d9);
3331 DestroyWindow(window1);
3332 return;
3334 IDirect3D9_Release(d3d9);
3336 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3337 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3338 ok(!!window2, "Failed to create a window.\n");
3339 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3340 ok(!!d3d9, "Failed to create a D3D object.\n");
3341 device2 = create_device(d3d9, window2, NULL);
3342 IDirect3D9_Release(d3d9);
3344 refcount = IDirect3DDevice9_Release(device2);
3345 ok(!refcount, "Device has %u references left.\n", refcount);
3346 refcount = IDirect3DDevice9_Release(device1);
3347 ok(!refcount, "Device has %u references left.\n", refcount);
3348 DestroyWindow(window2);
3349 DestroyWindow(window1);
3352 static HWND filter_messages;
3354 enum message_window
3356 DEVICE_WINDOW,
3357 FOCUS_WINDOW,
3360 struct message
3362 UINT message;
3363 enum message_window window;
3364 BOOL check_wparam;
3365 WPARAM expect_wparam;
3368 static const struct message *expect_messages;
3369 static HWND device_window, focus_window;
3370 static LONG windowposchanged_received, syscommand_received, wm_size_received;
3372 struct wndproc_thread_param
3374 HWND dummy_window;
3375 HANDLE window_created;
3376 HANDLE test_finished;
3377 BOOL running_in_foreground;
3380 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3382 if (filter_messages && filter_messages == hwnd)
3384 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3385 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3388 if (expect_messages)
3390 HWND w;
3392 switch (expect_messages->window)
3394 case DEVICE_WINDOW:
3395 w = device_window;
3396 break;
3398 case FOCUS_WINDOW:
3399 w = focus_window;
3400 break;
3402 default:
3403 w = NULL;
3404 break;
3407 if (hwnd == w && expect_messages->message == message)
3409 if (expect_messages->check_wparam)
3410 ok(wparam == expect_messages->expect_wparam,
3411 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3412 wparam, message, expect_messages->expect_wparam);
3414 ++expect_messages;
3418 /* KDE randomly does something with the hidden window during the
3419 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3420 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3421 * just flag WM_WINDOWPOSCHANGED as bad. */
3422 if (message == WM_WINDOWPOSCHANGED)
3423 InterlockedIncrement(&windowposchanged_received);
3424 else if (message == WM_SYSCOMMAND)
3425 InterlockedIncrement(&syscommand_received);
3426 else if (message == WM_SIZE)
3427 InterlockedIncrement(&wm_size_received);
3429 return DefWindowProcA(hwnd, message, wparam, lparam);
3432 static DWORD WINAPI wndproc_thread(void *param)
3434 struct wndproc_thread_param *p = param;
3435 DWORD res;
3436 BOOL ret;
3438 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3439 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3440 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3441 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3443 ret = SetEvent(p->window_created);
3444 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3446 for (;;)
3448 MSG msg;
3450 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3451 res = WaitForSingleObject(p->test_finished, 100);
3452 if (res == WAIT_OBJECT_0) break;
3453 if (res != WAIT_TIMEOUT)
3455 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3456 break;
3460 DestroyWindow(p->dummy_window);
3462 return 0;
3465 static void test_wndproc(void)
3467 struct wndproc_thread_param thread_params;
3468 struct device_desc device_desc;
3469 IDirect3DDevice9 *device;
3470 WNDCLASSA wc = {0};
3471 IDirect3D9 *d3d9;
3472 HANDLE thread;
3473 LONG_PTR proc;
3474 ULONG ref;
3475 DWORD res, tid;
3476 HWND tmp;
3477 UINT i, adapter_mode_count;
3478 HRESULT hr;
3479 D3DDISPLAYMODE d3ddm;
3480 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3481 DEVMODEW devmode;
3482 LONG change_ret;
3483 BOOL ret;
3485 static const struct message create_messages[] =
3487 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3488 /* Do not test wparam here. If device creation succeeds,
3489 * wparam is WA_ACTIVE. If device creation fails (testbot)
3490 * wparam is set to WA_INACTIVE on some Windows versions. */
3491 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3492 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3493 {0, 0, FALSE, 0},
3495 static const struct message focus_loss_messages[] =
3497 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3498 * not reliable on X11 WMs. When the window focus follows the
3499 * mouse pointer the message is not sent.
3500 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3501 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3502 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3503 * not deterministic. */
3504 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3505 /* Windows sends WM_ACTIVATE to the device window, indicating that
3506 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3507 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3508 * leaves the device window active, breaking re-activation in the
3509 * lost device test.
3510 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3511 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3512 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3513 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3514 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3515 * not deterministic. It may be sent after the focus window handling
3516 * or before. */
3517 {0, 0, FALSE, 0},
3519 static const struct message focus_loss_messages_nowc[] =
3521 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3522 * not reliable on X11 WMs. When the window focus follows the
3523 * mouse pointer the message is not sent.
3524 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3525 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3526 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3527 {0, 0, FALSE, 0},
3529 static const struct message reactivate_messages[] =
3531 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3532 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3533 /* optional WM_MOVE here if size changed */
3534 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3535 {0, 0, FALSE, 0},
3537 static const struct message reactivate_messages_nowc[] =
3539 /* We're activating the device window before activating the
3540 * focus window, so no ACTIVATEAPP message is sent. */
3541 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3542 {0, 0, FALSE, 0},
3544 static const struct message focus_loss_messages_hidden[] =
3546 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3547 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3548 {0, 0, FALSE, 0},
3550 static const struct message focus_loss_messages_filtered[] =
3552 /* WM_ACTIVATE is delivered to the window proc because it is
3553 * generated by SetForegroundWindow before the d3d routine
3554 * starts it work. Don't check for it due to focus-follows-mouse
3555 * WMs though. */
3556 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3557 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3558 {0, 0, FALSE, 0},
3560 static const struct message reactivate_messages_filtered[] =
3562 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3563 {0, 0, FALSE, 0},
3565 static const struct message sc_restore_messages[] =
3567 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3568 * processed it. Our wndproc has no way to prevent d3d from
3569 * handling the message. The second DefWindowProc call done by
3570 * our wndproc doesn't do any changes to the window because it
3571 * is already restored due to d3d's handling. */
3572 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3573 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3574 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3575 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3576 {0, 0, FALSE, 0},
3578 static const struct message sc_minimize_messages[] =
3580 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3581 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3582 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3583 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3584 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3585 {0, 0, FALSE, 0},
3587 static const struct message sc_maximize_messages[] =
3589 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3590 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3591 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3592 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3593 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3594 {0, 0, FALSE, 0},
3596 static const struct
3598 DWORD create_flags;
3599 const struct message *focus_loss_messages, *reactivate_messages;
3600 BOOL iconic;
3602 tests[] =
3604 {0, focus_loss_messages, reactivate_messages, TRUE},
3605 {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, reactivate_messages_nowc, FALSE},
3608 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3609 ok(!!d3d9, "Failed to create a D3D object.\n");
3611 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3612 for (i = 0; i < adapter_mode_count; ++i)
3614 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3615 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3617 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3618 continue;
3619 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3620 * refuses to create a device at these sizes. */
3621 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3622 continue;
3624 if (!user32_width)
3626 user32_width = d3ddm.Width;
3627 user32_height = d3ddm.Height;
3628 continue;
3631 /* Make sure the d3d mode is smaller in width or height and at most
3632 * equal in the other dimension than the mode passed to
3633 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3634 * the ChangeDisplaySettings parameters + 12. */
3635 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3636 continue;
3637 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3639 d3d_width = d3ddm.Width;
3640 d3d_height = d3ddm.Height;
3641 break;
3643 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3645 d3d_width = user32_width;
3646 d3d_height = user32_height;
3647 user32_width = d3ddm.Width;
3648 user32_height = d3ddm.Height;
3649 break;
3653 if (!d3d_width)
3655 skip("Could not find adequate modes, skipping mode tests.\n");
3656 IDirect3D9_Release(d3d9);
3657 return;
3660 wc.lpfnWndProc = test_proc;
3661 wc.lpszClassName = "d3d9_test_wndproc_wc";
3662 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3664 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3665 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3666 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3667 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3669 memset(&devmode, 0, sizeof(devmode));
3670 devmode.dmSize = sizeof(devmode);
3671 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
3673 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3674 devmode.dmPelsWidth = user32_width;
3675 devmode.dmPelsHeight = user32_height;
3676 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3677 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3679 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3680 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3681 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3682 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3683 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3684 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3686 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3687 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3689 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3690 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3691 (LONG_PTR)test_proc, proc);
3692 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3693 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3694 (LONG_PTR)test_proc, proc);
3696 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3697 device_window, focus_window, thread_params.dummy_window);
3699 tmp = GetFocus();
3700 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3701 if (thread_params.running_in_foreground)
3703 tmp = GetForegroundWindow();
3704 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3705 thread_params.dummy_window, tmp);
3707 else
3708 skip("Not running in foreground, skip foreground window test\n");
3710 flush_events();
3712 expect_messages = create_messages;
3714 device_desc.device_window = device_window;
3715 device_desc.width = d3d_width;
3716 device_desc.height = d3d_height;
3717 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3718 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3720 skip("Failed to create a D3D device, skipping tests.\n");
3721 goto done;
3724 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3725 expect_messages->message, expect_messages->window, i);
3726 expect_messages = NULL;
3728 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3730 tmp = GetFocus();
3731 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3732 tmp = GetForegroundWindow();
3733 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3735 SetForegroundWindow(focus_window);
3736 flush_events();
3738 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3739 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3740 (LONG_PTR)test_proc, proc, i);
3742 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3743 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3744 (LONG_PTR)test_proc, i);
3746 /* Change the mode while the device is in use and then drop focus. */
3747 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3748 devmode.dmPelsWidth = user32_width;
3749 devmode.dmPelsHeight = user32_height;
3750 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3751 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3753 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3754 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3755 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3756 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3757 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3758 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3760 expect_messages = tests[i].focus_loss_messages;
3761 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3762 * manually changing the focus. It generates the same messages, but the task
3763 * bar still shows the previous foreground window as active, and the window has
3764 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3765 * the device is difficult, see below. */
3766 SetForegroundWindow(GetDesktopWindow());
3767 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3768 expect_messages->message, expect_messages->window, i);
3769 expect_messages = NULL;
3770 tmp = GetFocus();
3771 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3772 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3774 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3775 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3777 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3778 ok(ret, "Failed to get display mode.\n");
3779 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3780 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3781 devmode.dmPelsWidth, devmode.dmPelsHeight);
3783 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3784 * done before the focus window is restored. This makes sense to some extent
3785 * because minimizing the window on focus loss is the application's job if this
3786 * flag is set. */
3787 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3789 ShowWindow(device_window, SW_MINIMIZE);
3790 ShowWindow(device_window, SW_RESTORE);
3792 flush_events();
3794 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3795 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3796 * restore is triggered by the user. */
3797 expect_messages = tests[i].reactivate_messages;
3798 ShowWindow(focus_window, SW_MINIMIZE);
3799 ShowWindow(focus_window, SW_RESTORE);
3800 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3801 SetForegroundWindow(focus_window);
3802 flush_events();
3803 SetForegroundWindow(focus_window);
3804 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3805 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3806 expect_messages->message, expect_messages->window, i);
3807 expect_messages = NULL;
3809 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3810 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3812 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3813 ok(ret, "Failed to get display mode.\n");
3814 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3815 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3816 devmode.dmPelsWidth, devmode.dmPelsHeight);
3818 hr = reset_device(device, &device_desc);
3819 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3821 ShowWindow(device_window, SW_HIDE);
3822 flush_events();
3824 expect_messages = focus_loss_messages_hidden;
3825 windowposchanged_received = 0;
3826 SetForegroundWindow(GetDesktopWindow());
3827 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3828 expect_messages->message, expect_messages->window, i);
3829 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3830 expect_messages = NULL;
3831 flush_events();
3833 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3834 ok(ret, "Failed to get display mode.\n");
3835 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3836 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3838 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3839 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3840 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3841 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3842 flush_events();
3844 syscommand_received = 0;
3845 expect_messages = sc_restore_messages;
3846 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3847 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3848 expect_messages->message, expect_messages->window, i);
3849 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3850 expect_messages = NULL;
3851 flush_events();
3853 expect_messages = sc_minimize_messages;
3854 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3855 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3856 expect_messages->message, expect_messages->window, i);
3857 expect_messages = NULL;
3858 flush_events();
3860 expect_messages = sc_maximize_messages;
3861 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3862 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3863 expect_messages->message, expect_messages->window, i);
3864 expect_messages = NULL;
3865 flush_events();
3867 SetForegroundWindow(GetDesktopWindow());
3868 ShowWindow(device_window, SW_MINIMIZE);
3869 ShowWindow(device_window, SW_RESTORE);
3870 ShowWindow(focus_window, SW_MINIMIZE);
3871 ShowWindow(focus_window, SW_RESTORE);
3872 SetForegroundWindow(focus_window);
3873 flush_events();
3875 /* Releasing a device in lost state breaks follow-up tests on native. */
3876 hr = reset_device(device, &device_desc);
3877 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3879 filter_messages = focus_window;
3881 ref = IDirect3DDevice9_Release(device);
3882 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3884 /* Fix up the mode until Wine's device release behavior is fixed. */
3885 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3886 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3888 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3889 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3890 (LONG_PTR)test_proc, proc, i);
3892 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3893 * on native in the test below. It isn't needed anyways. Creating the third
3894 * device will show it again. */
3895 filter_messages = NULL;
3896 ShowWindow(device_window, SW_HIDE);
3897 /* Remove the maximized state from the SYSCOMMAND test while we're not
3898 * interfering with a device. */
3899 ShowWindow(focus_window, SW_SHOWNORMAL);
3900 filter_messages = focus_window;
3902 device_desc.device_window = focus_window;
3903 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3905 skip("Failed to create a D3D device, skipping tests.\n");
3906 goto done;
3908 filter_messages = NULL;
3909 SetForegroundWindow(focus_window); /* For KDE. */
3910 flush_events();
3912 expect_messages = focus_loss_messages_filtered;
3913 windowposchanged_received = 0;
3914 SetForegroundWindow(GetDesktopWindow());
3915 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3916 expect_messages->message, expect_messages->window, i);
3917 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3918 expect_messages = NULL;
3920 /* The window is iconic even though no message was sent. */
3921 ok(!IsIconic(focus_window) == !tests[i].iconic,
3922 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
3924 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3925 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3927 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3928 ShowWindow(focus_window, SW_MINIMIZE);
3930 syscommand_received = 0;
3931 expect_messages = sc_restore_messages;
3932 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3933 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3934 expect_messages->message, expect_messages->window, i);
3935 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3936 expect_messages = NULL;
3937 flush_events();
3939 /* For FVWM. */
3940 ShowWindow(focus_window, SW_RESTORE);
3941 flush_events();
3943 expect_messages = sc_minimize_messages;
3944 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3945 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3946 expect_messages->message, expect_messages->window, i);
3947 expect_messages = NULL;
3948 flush_events();
3950 expect_messages = sc_maximize_messages;
3951 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3952 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3953 expect_messages->message, expect_messages->window, i);
3954 expect_messages = NULL;
3955 flush_events();
3957 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
3958 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
3959 SetForegroundWindow(GetDesktopWindow());
3960 flush_events();
3961 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
3962 flush_events();
3964 expect_messages = reactivate_messages_filtered;
3965 windowposchanged_received = 0;
3966 SetForegroundWindow(focus_window);
3967 flush_events();
3968 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3969 expect_messages->message, expect_messages->window, i);
3970 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
3971 ok(!windowposchanged_received || broken(1),
3972 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3973 expect_messages = NULL;
3975 filter_messages = focus_window;
3976 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3977 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3979 hr = reset_device(device, &device_desc);
3980 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3982 ref = IDirect3DDevice9_Release(device);
3983 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3985 device_desc.device_window = device_window;
3986 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3988 skip("Failed to create a D3D device, skipping tests.\n");
3989 goto done;
3992 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3993 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3994 (LONG_PTR)test_proc, i);
3996 ref = IDirect3DDevice9_Release(device);
3997 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3999 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4000 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4001 (LONG_PTR)DefWindowProcA, proc, i);
4003 done:
4004 filter_messages = NULL;
4005 DestroyWindow(device_window);
4006 DestroyWindow(focus_window);
4007 SetEvent(thread_params.test_finished);
4008 WaitForSingleObject(thread, INFINITE);
4009 CloseHandle(thread);
4012 IDirect3D9_Release(d3d9);
4013 CloseHandle(thread_params.test_finished);
4014 CloseHandle(thread_params.window_created);
4015 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4018 static void test_wndproc_windowed(void)
4020 struct wndproc_thread_param thread_params;
4021 struct device_desc device_desc;
4022 IDirect3DDevice9 *device;
4023 WNDCLASSA wc = {0};
4024 IDirect3D9 *d3d9;
4025 HANDLE thread;
4026 LONG_PTR proc;
4027 HRESULT hr;
4028 ULONG ref;
4029 DWORD res, tid;
4030 HWND tmp;
4032 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4033 ok(!!d3d9, "Failed to create a D3D object.\n");
4035 wc.lpfnWndProc = test_proc;
4036 wc.lpszClassName = "d3d9_test_wndproc_wc";
4037 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4039 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4040 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4041 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4042 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4044 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4045 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4046 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4047 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4048 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4049 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4050 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4051 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4053 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4054 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4056 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4057 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4058 (LONG_PTR)test_proc, proc);
4059 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4060 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4061 (LONG_PTR)test_proc, proc);
4063 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4064 device_window, focus_window, thread_params.dummy_window);
4066 tmp = GetFocus();
4067 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4068 if (thread_params.running_in_foreground)
4070 tmp = GetForegroundWindow();
4071 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4072 thread_params.dummy_window, tmp);
4074 else
4075 skip("Not running in foreground, skip foreground window test\n");
4077 filter_messages = focus_window;
4079 device_desc.device_window = device_window;
4080 device_desc.width = 640;
4081 device_desc.height = 480;
4082 device_desc.flags = 0;
4083 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4085 skip("Failed to create a D3D device, skipping tests.\n");
4086 goto done;
4089 tmp = GetFocus();
4090 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4091 tmp = GetForegroundWindow();
4092 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4093 thread_params.dummy_window, tmp);
4095 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4096 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4097 (LONG_PTR)test_proc, proc);
4099 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4100 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4101 (LONG_PTR)test_proc, proc);
4103 filter_messages = NULL;
4105 device_desc.width = registry_mode.dmPelsWidth;
4106 device_desc.height = registry_mode.dmPelsHeight;
4107 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4108 hr = reset_device(device, &device_desc);
4109 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4111 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4112 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4113 (LONG_PTR)test_proc, proc);
4115 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4116 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4118 device_desc.flags = 0;
4119 hr = reset_device(device, &device_desc);
4120 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4122 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4123 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4124 (LONG_PTR)test_proc, proc);
4126 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4127 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4128 (LONG_PTR)test_proc, proc);
4130 filter_messages = focus_window;
4132 ref = IDirect3DDevice9_Release(device);
4133 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4135 filter_messages = device_window;
4137 device_desc.device_window = focus_window;
4138 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4140 skip("Failed to create a D3D device, skipping tests.\n");
4141 goto done;
4144 filter_messages = NULL;
4146 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4147 hr = reset_device(device, &device_desc);
4148 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4150 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4151 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4152 (LONG_PTR)test_proc, proc);
4154 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4155 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4157 device_desc.flags = 0;
4158 hr = reset_device(device, &device_desc);
4159 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4161 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4162 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4163 (LONG_PTR)test_proc, proc);
4165 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4166 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4167 (LONG_PTR)test_proc, proc);
4169 filter_messages = device_window;
4171 ref = IDirect3DDevice9_Release(device);
4172 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4174 device_desc.device_window = device_window;
4175 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4177 skip("Failed to create a D3D device, skipping tests.\n");
4178 goto done;
4181 filter_messages = NULL;
4183 device_desc.device_window = device_window;
4184 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4185 hr = reset_device(device, &device_desc);
4186 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4188 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4189 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4190 (LONG_PTR)test_proc, proc);
4192 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4193 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4195 device_desc.flags = 0;
4196 hr = reset_device(device, &device_desc);
4197 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4199 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4200 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4201 (LONG_PTR)test_proc, proc);
4203 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4204 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4205 (LONG_PTR)test_proc, proc);
4207 filter_messages = device_window;
4209 ref = IDirect3DDevice9_Release(device);
4210 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4212 done:
4213 filter_messages = NULL;
4214 IDirect3D9_Release(d3d9);
4216 SetEvent(thread_params.test_finished);
4217 WaitForSingleObject(thread, INFINITE);
4218 CloseHandle(thread_params.test_finished);
4219 CloseHandle(thread_params.window_created);
4220 CloseHandle(thread);
4222 DestroyWindow(device_window);
4223 DestroyWindow(focus_window);
4224 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4227 static void test_reset_fullscreen(void)
4229 struct device_desc device_desc;
4230 D3DDISPLAYMODE d3ddm, d3ddm2;
4231 unsigned int mode_count, i;
4232 IDirect3DDevice9 *device;
4233 WNDCLASSEXA wc = {0};
4234 IDirect3D9 *d3d;
4235 HRESULT hr;
4236 ATOM atom;
4237 static const struct message messages[] =
4239 /* Windows usually sends wparam = TRUE, except on the testbot,
4240 * where it randomly sends FALSE. Ignore it. */
4241 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4242 {0, 0, FALSE, 0},
4245 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4246 ok(!!d3d, "Failed to create a D3D object.\n");
4247 expect_messages = messages;
4249 wc.cbSize = sizeof(wc);
4250 wc.lpfnWndProc = test_proc;
4251 wc.lpszClassName = "test_reset_fullscreen";
4253 atom = RegisterClassExA(&wc);
4254 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4256 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4257 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4258 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4261 * Create a device in windowed mode.
4262 * Since the device is windowed and we haven't called any methods that
4263 * could show the window (such as ShowWindow or SetWindowPos) yet,
4264 * WM_ACTIVATEAPP will not have been sent.
4266 if (!(device = create_device(d3d, device_window, NULL)))
4268 skip("Unable to create device. Skipping test.\n");
4269 goto cleanup;
4273 * Switch to fullscreen mode.
4274 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4275 * message to be sent.
4277 device_desc.width = registry_mode.dmPelsWidth;
4278 device_desc.height = registry_mode.dmPelsHeight;
4279 device_desc.device_window = device_window;
4280 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4281 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4283 flush_events();
4284 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4285 expect_messages = NULL;
4287 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
4288 mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
4289 for (i = 0; i < mode_count; ++i)
4291 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
4292 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4294 if (d3ddm2.Width != d3ddm.Width || d3ddm2.Height != d3ddm.Height)
4295 break;
4297 if (i == mode_count)
4299 skip("Could not find a suitable display mode.\n");
4300 goto cleanup;
4303 wm_size_received = 0;
4305 /* Fullscreen mode change. */
4306 device_desc.width = d3ddm2.Width;
4307 device_desc.height = d3ddm2.Height;
4308 device_desc.device_window = device_window;
4309 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4310 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4312 flush_events();
4313 ok(!wm_size_received, "Received unexpected WM_SIZE message.\n");
4315 cleanup:
4316 if (device) IDirect3DDevice9_Release(device);
4317 IDirect3D9_Release(d3d);
4318 DestroyWindow(device_window);
4319 device_window = focus_window = NULL;
4320 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4324 static inline void set_fpu_cw(WORD cw)
4326 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4327 #define D3D9_TEST_SET_FPU_CW 1
4328 __asm__ volatile ("fnclex");
4329 __asm__ volatile ("fldcw %0" : : "m" (cw));
4330 #elif defined(__i386__) && defined(_MSC_VER)
4331 #define D3D9_TEST_SET_FPU_CW 1
4332 __asm fnclex;
4333 __asm fldcw cw;
4334 #endif
4337 static inline WORD get_fpu_cw(void)
4339 WORD cw = 0;
4340 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4341 #define D3D9_TEST_GET_FPU_CW 1
4342 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4343 #elif defined(__i386__) && defined(_MSC_VER)
4344 #define D3D9_TEST_GET_FPU_CW 1
4345 __asm fnstcw cw;
4346 #endif
4347 return cw;
4350 static WORD callback_cw, callback_set_cw;
4351 static DWORD callback_tid;
4353 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4355 *out = NULL;
4356 return E_NOINTERFACE;
4359 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4361 callback_cw = get_fpu_cw();
4362 set_fpu_cw(callback_set_cw);
4363 callback_tid = GetCurrentThreadId();
4364 return 2;
4367 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4369 callback_cw = get_fpu_cw();
4370 set_fpu_cw(callback_set_cw);
4371 callback_tid = GetCurrentThreadId();
4372 return 1;
4375 static const IUnknownVtbl dummy_object_vtbl =
4377 dummy_object_QueryInterface,
4378 dummy_object_AddRef,
4379 dummy_object_Release,
4382 static const GUID d3d9_private_data_test_guid =
4384 0xfdb37466,
4385 0x428f,
4386 0x4edf,
4387 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4390 static void test_fpu_setup(void)
4392 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4393 struct device_desc device_desc;
4394 IDirect3DDevice9 *device;
4395 HWND window = NULL;
4396 IDirect3D9 *d3d9;
4397 WORD cw;
4398 IDirect3DSurface9 *surface;
4399 HRESULT hr;
4400 IUnknown dummy_object = {&dummy_object_vtbl};
4402 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4403 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4404 ok(!!window, "Failed to create a window.\n");
4405 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4406 ok(!!d3d9, "Failed to create a D3D object.\n");
4408 device_desc.device_window = window;
4409 device_desc.width = 640;
4410 device_desc.height = 480;
4411 device_desc.flags = 0;
4413 set_fpu_cw(0xf60);
4414 cw = get_fpu_cw();
4415 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4417 if (!(device = create_device(d3d9, window, &device_desc)))
4419 skip("Failed to create a 3D device, skipping test.\n");
4420 set_fpu_cw(0x37f);
4421 goto done;
4424 cw = get_fpu_cw();
4425 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4427 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4428 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4430 callback_set_cw = 0xf60;
4431 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4432 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4433 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4434 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4435 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4436 cw = get_fpu_cw();
4437 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4439 callback_cw = 0;
4440 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4441 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4442 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4443 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4444 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4446 callback_set_cw = 0x7f;
4447 set_fpu_cw(0x7f);
4449 IDirect3DSurface9_Release(surface);
4451 callback_cw = 0;
4452 IDirect3DDevice9_Release(device);
4453 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4454 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4456 cw = get_fpu_cw();
4457 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4458 set_fpu_cw(0xf60);
4459 cw = get_fpu_cw();
4460 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4462 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4463 device = create_device(d3d9, window, &device_desc);
4464 ok(device != NULL, "CreateDevice failed.\n");
4466 cw = get_fpu_cw();
4467 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4469 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4470 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4472 callback_cw = 0;
4473 callback_set_cw = 0x37f;
4474 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4475 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4476 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4477 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4478 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4479 cw = get_fpu_cw();
4480 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4482 IDirect3DSurface9_Release(surface);
4484 callback_cw = 0;
4485 IDirect3DDevice9_Release(device);
4486 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4487 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4489 done:
4490 IDirect3D9_Release(d3d9);
4491 DestroyWindow(window);
4492 #endif
4495 static void test_window_style(void)
4497 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4498 LONG device_style, device_exstyle;
4499 LONG focus_style, focus_exstyle;
4500 struct device_desc device_desc;
4501 LONG style, expected_style;
4502 IDirect3DDevice9 *device;
4503 IDirect3D9 *d3d9;
4504 HRESULT hr;
4505 ULONG ref;
4506 BOOL ret;
4507 static const struct
4509 DWORD device_flags;
4510 LONG style, focus_loss_style, exstyle;
4512 tests[] =
4514 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4515 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4517 unsigned int i;
4519 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4520 ok(!!d3d9, "Failed to create a D3D object.\n");
4521 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4523 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
4525 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4526 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4527 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4528 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4530 device_style = GetWindowLongA(device_window, GWL_STYLE);
4531 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4532 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4533 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4535 GetWindowRect(focus_window, &focus_rect);
4536 GetWindowRect(device_window, &device_rect);
4538 device_desc.device_window = device_window;
4539 device_desc.width = registry_mode.dmPelsWidth;
4540 device_desc.height = registry_mode.dmPelsHeight;
4541 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4542 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4544 skip("Failed to create a D3D device, skipping tests.\n");
4545 DestroyWindow(device_window);
4546 DestroyWindow(focus_window);
4547 break;
4550 style = GetWindowLongA(device_window, GWL_STYLE);
4551 expected_style = device_style | tests[i].style;
4552 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4553 expected_style, style, i);
4554 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4555 expected_style = device_exstyle | tests[i].exstyle;
4556 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4557 expected_style, style, i);
4559 style = GetWindowLongA(focus_window, GWL_STYLE);
4560 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4561 focus_style, style, i);
4562 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4563 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4564 focus_exstyle, style, i);
4566 GetWindowRect(device_window, &r);
4567 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4568 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4569 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4570 else
4571 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4572 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4573 GetClientRect(device_window, &r2);
4574 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4575 GetWindowRect(focus_window, &r);
4576 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4577 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4579 device_desc.flags = 0;
4580 hr = reset_device(device, &device_desc);
4581 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4583 style = GetWindowLongA(device_window, GWL_STYLE);
4584 expected_style = device_style | tests[i].style;
4585 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4586 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4587 expected_style, style, i);
4588 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4589 expected_style = device_exstyle | tests[i].exstyle;
4590 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4591 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4592 expected_style, style, i);
4594 style = GetWindowLongA(focus_window, GWL_STYLE);
4595 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4596 focus_style, style, i);
4597 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4598 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4599 focus_exstyle, style, i);
4601 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4602 hr = reset_device(device, &device_desc);
4603 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4604 ret = SetForegroundWindow(GetDesktopWindow());
4605 ok(ret, "Failed to set foreground window.\n");
4607 style = GetWindowLongA(device_window, GWL_STYLE);
4608 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4609 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4610 expected_style, style);
4611 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4612 expected_style = device_exstyle | tests[i].exstyle;
4613 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4614 expected_style, style);
4616 style = GetWindowLongA(focus_window, GWL_STYLE);
4617 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4618 focus_style, style);
4619 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4620 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4621 focus_exstyle, style);
4623 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4624 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4625 * like a good idea to reset it first. */
4626 ShowWindow(focus_window, SW_MINIMIZE);
4627 ShowWindow(focus_window, SW_RESTORE);
4628 ret = SetForegroundWindow(focus_window);
4629 ok(ret, "Failed to set foreground window.\n");
4630 flush_events();
4631 hr = reset_device(device, &device_desc);
4632 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4634 ref = IDirect3DDevice9_Release(device);
4635 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4637 DestroyWindow(device_window);
4638 DestroyWindow(focus_window);
4640 IDirect3D9_Release(d3d9);
4643 static const POINT *expect_pos;
4645 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4647 if (message == WM_MOUSEMOVE)
4649 if (expect_pos && expect_pos->x && expect_pos->y)
4651 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4653 ClientToScreen(window, &p);
4654 if (expect_pos->x == p.x && expect_pos->y == p.y)
4655 ++expect_pos;
4659 return DefWindowProcA(window, message, wparam, lparam);
4662 static void test_cursor_pos(void)
4664 IDirect3DSurface9 *cursor;
4665 IDirect3DDevice9 *device;
4666 WNDCLASSA wc = {0};
4667 IDirect3D9 *d3d9;
4668 UINT refcount;
4669 HWND window;
4670 HRESULT hr;
4671 BOOL ret;
4673 /* Note that we don't check for movement we're not supposed to receive.
4674 * That's because it's hard to distinguish from the user accidentally
4675 * moving the mouse. */
4676 static const POINT points[] =
4678 {50, 50},
4679 {75, 75},
4680 {100, 100},
4681 {125, 125},
4682 {150, 150},
4683 {125, 125},
4684 {150, 150},
4685 {150, 150},
4686 {0, 0},
4689 wc.lpfnWndProc = test_cursor_proc;
4690 wc.lpszClassName = "d3d9_test_cursor_wc";
4691 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4692 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4693 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4694 ShowWindow(window, SW_SHOW);
4695 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4696 ok(!!d3d9, "Failed to create a D3D object.\n");
4698 device = create_device(d3d9, window, NULL);
4699 if (!device)
4701 skip("Failed to create a D3D device, skipping tests.\n");
4702 goto done;
4705 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4706 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4707 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4708 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4709 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4710 IDirect3DSurface9_Release(cursor);
4711 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4712 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4714 flush_events();
4715 expect_pos = points;
4717 ret = SetCursorPos(50, 50);
4718 ok(ret, "Failed to set cursor position.\n");
4719 flush_events();
4721 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4722 flush_events();
4723 /* SetCursorPosition() eats duplicates. */
4724 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4725 flush_events();
4727 ret = SetCursorPos(100, 100);
4728 ok(ret, "Failed to set cursor position.\n");
4729 flush_events();
4730 /* Even if the position was set with SetCursorPos(). */
4731 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4732 flush_events();
4734 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4735 flush_events();
4736 ret = SetCursorPos(150, 150);
4737 ok(ret, "Failed to set cursor position.\n");
4738 flush_events();
4739 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4740 flush_events();
4742 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4743 flush_events();
4744 /* SetCursorPos() doesn't. */
4745 ret = SetCursorPos(150, 150);
4746 ok(ret, "Failed to set cursor position.\n");
4747 flush_events();
4749 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4750 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4752 refcount = IDirect3DDevice9_Release(device);
4753 ok(!refcount, "Device has %u references left.\n", refcount);
4754 done:
4755 DestroyWindow(window);
4756 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4757 IDirect3D9_Release(d3d9);
4760 static void test_mode_change(void)
4762 RECT d3d_rect, focus_rect, r;
4763 struct device_desc device_desc;
4764 IDirect3DSurface9 *backbuffer;
4765 IDirect3DDevice9 *device;
4766 D3DSURFACE_DESC desc;
4767 IDirect3D9 *d3d9;
4768 DEVMODEW devmode;
4769 ULONG refcount;
4770 UINT adapter_mode_count, i;
4771 HRESULT hr;
4772 DWORD ret;
4773 LONG change_ret;
4774 D3DDISPLAYMODE d3ddm;
4775 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4777 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4778 ok(!!d3d9, "Failed to create a D3D object.\n");
4780 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4781 for (i = 0; i < adapter_mode_count; ++i)
4783 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4784 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4786 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4787 continue;
4788 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4789 * refuses to create a device at these sizes. */
4790 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4791 continue;
4793 if (!user32_width)
4795 user32_width = d3ddm.Width;
4796 user32_height = d3ddm.Height;
4797 continue;
4800 /* Make sure the d3d mode is smaller in width or height and at most
4801 * equal in the other dimension than the mode passed to
4802 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4803 * the ChangeDisplaySettings parameters + 12. */
4804 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4805 continue;
4806 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4808 d3d_width = d3ddm.Width;
4809 d3d_height = d3ddm.Height;
4810 break;
4812 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4814 d3d_width = user32_width;
4815 d3d_height = user32_height;
4816 user32_width = d3ddm.Width;
4817 user32_height = d3ddm.Height;
4818 break;
4822 if (!d3d_width)
4824 skip("Could not find adequate modes, skipping mode tests.\n");
4825 IDirect3D9_Release(d3d9);
4826 return;
4829 memset(&devmode, 0, sizeof(devmode));
4830 devmode.dmSize = sizeof(devmode);
4831 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4832 devmode.dmPelsWidth = user32_width;
4833 devmode.dmPelsHeight = user32_height;
4834 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4835 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4837 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4838 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4839 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4840 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4842 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4843 GetWindowRect(focus_window, &focus_rect);
4845 device_desc.device_window = device_window;
4846 device_desc.width = d3d_width;
4847 device_desc.height = d3d_height;
4848 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4849 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4851 skip("Failed to create a D3D device, skipping tests.\n");
4852 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4853 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4854 goto done;
4857 devmode.dmPelsWidth = user32_width;
4858 devmode.dmPelsHeight = user32_height;
4859 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4860 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4862 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4863 ok(ret, "Failed to get display mode.\n");
4864 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4865 "Expected resolution %ux%u, got %ux%u.\n",
4866 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4868 GetWindowRect(device_window, &r);
4869 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
4870 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
4871 GetWindowRect(focus_window, &r);
4872 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
4873 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
4875 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4876 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
4877 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
4878 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
4879 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4880 desc.Width, d3d_width);
4881 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4882 desc.Height, d3d_height);
4883 IDirect3DSurface9_Release(backbuffer);
4885 refcount = IDirect3DDevice9_Release(device);
4886 ok(!refcount, "Device has %u references left.\n", refcount);
4888 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4889 ok(ret, "Failed to get display mode.\n");
4890 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4891 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4892 "Expected resolution %ux%u, got %ux%u.\n",
4893 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4895 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4896 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4898 /* The mode restore also happens when the device was created at the original screen size. */
4900 device_desc.device_window = device_window;
4901 device_desc.width = registry_mode.dmPelsWidth;
4902 device_desc.height = registry_mode.dmPelsHeight;
4903 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4904 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4906 devmode.dmPelsWidth = user32_width;
4907 devmode.dmPelsHeight = user32_height;
4908 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4909 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4911 refcount = IDirect3DDevice9_Release(device);
4912 ok(!refcount, "Device has %u references left.\n", refcount);
4914 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4915 ok(ret, "Failed to get display mode.\n");
4916 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4917 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4918 "Expected resolution %ux%u, got %ux%u.\n",
4919 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4921 done:
4922 DestroyWindow(device_window);
4923 DestroyWindow(focus_window);
4924 IDirect3D9_Release(d3d9);
4927 static void test_device_window_reset(void)
4929 RECT fullscreen_rect, device_rect, r;
4930 struct device_desc device_desc;
4931 IDirect3DDevice9 *device;
4932 WNDCLASSA wc = {0};
4933 IDirect3D9 *d3d9;
4934 LONG_PTR proc;
4935 HRESULT hr;
4936 ULONG ref;
4938 wc.lpfnWndProc = test_proc;
4939 wc.lpszClassName = "d3d9_test_wndproc_wc";
4940 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4942 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4943 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4944 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4945 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4946 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4947 ok(!!d3d9, "Failed to create a D3D object.\n");
4949 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4950 GetWindowRect(device_window, &device_rect);
4952 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4953 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4954 (LONG_PTR)test_proc, proc);
4955 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4956 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4957 (LONG_PTR)test_proc, proc);
4959 device_desc.device_window = NULL;
4960 device_desc.width = registry_mode.dmPelsWidth;
4961 device_desc.height = registry_mode.dmPelsHeight;
4962 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4963 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4965 skip("Failed to create a D3D device, skipping tests.\n");
4966 goto done;
4969 GetWindowRect(focus_window, &r);
4970 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4971 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4972 GetWindowRect(device_window, &r);
4973 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
4974 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
4976 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4977 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4978 (LONG_PTR)test_proc, proc);
4979 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4980 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4982 device_desc.device_window = device_window;
4983 hr = reset_device(device, &device_desc);
4984 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4986 GetWindowRect(focus_window, &r);
4987 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4988 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4989 GetWindowRect(device_window, &r);
4990 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4991 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4993 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4994 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4995 (LONG_PTR)test_proc, proc);
4996 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4997 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4999 ref = IDirect3DDevice9_Release(device);
5000 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5002 done:
5003 IDirect3D9_Release(d3d9);
5004 DestroyWindow(device_window);
5005 DestroyWindow(focus_window);
5006 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
5009 static void test_reset_resources(void)
5011 IDirect3DSurface9 *surface, *rt;
5012 IDirect3DTexture9 *texture;
5013 IDirect3DDevice9 *device;
5014 IDirect3D9 *d3d9;
5015 unsigned int i;
5016 D3DCAPS9 caps;
5017 HWND window;
5018 HRESULT hr;
5019 ULONG ref;
5021 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5022 0, 0, 640, 480, 0, 0, 0, 0);
5023 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5024 ok(!!d3d9, "Failed to create a D3D object.\n");
5026 if (!(device = create_device(d3d9, window, NULL)))
5028 skip("Failed to create a D3D device, skipping tests.\n");
5029 goto done;
5032 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5033 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5035 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5036 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5037 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5038 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5039 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5040 IDirect3DSurface9_Release(surface);
5042 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5044 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5045 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5046 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5047 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5048 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5049 IDirect3DTexture9_Release(texture);
5050 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5051 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5052 IDirect3DSurface9_Release(surface);
5055 hr = reset_device(device, NULL);
5056 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5058 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5059 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5060 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5061 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5062 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5063 IDirect3DSurface9_Release(surface);
5064 IDirect3DSurface9_Release(rt);
5066 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5068 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5069 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5072 ref = IDirect3DDevice9_Release(device);
5073 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5075 done:
5076 IDirect3D9_Release(d3d9);
5077 DestroyWindow(window);
5080 static void test_set_rt_vp_scissor(void)
5082 IDirect3DStateBlock9 *stateblock;
5083 IDirect3DDevice9 *device;
5084 IDirect3DSurface9 *rt;
5085 IDirect3D9 *d3d9;
5086 D3DVIEWPORT9 vp;
5087 UINT refcount;
5088 HWND window;
5089 HRESULT hr;
5090 RECT rect;
5092 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5093 0, 0, 640, 480, 0, 0, 0, 0);
5094 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5095 ok(!!d3d9, "Failed to create a D3D object.\n");
5096 if (!(device = create_device(d3d9, window, NULL)))
5098 skip("Failed to create a D3D device, skipping tests.\n");
5099 DestroyWindow(window);
5100 return;
5103 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5104 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5105 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5107 hr = IDirect3DDevice9_GetViewport(device, &vp);
5108 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5109 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5110 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5111 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5112 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5113 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5114 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5116 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5117 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5118 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5119 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5121 hr = IDirect3DDevice9_BeginStateBlock(device);
5122 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5124 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5125 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5127 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5128 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5129 IDirect3DStateBlock9_Release(stateblock);
5131 hr = IDirect3DDevice9_GetViewport(device, &vp);
5132 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5133 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5134 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5135 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5136 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5137 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5138 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5140 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5141 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5142 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5143 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5145 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5146 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5148 vp.X = 10;
5149 vp.Y = 20;
5150 vp.Width = 30;
5151 vp.Height = 40;
5152 vp.MinZ = 0.25f;
5153 vp.MaxZ = 0.75f;
5154 hr = IDirect3DDevice9_SetViewport(device, &vp);
5155 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5157 SetRect(&rect, 50, 60, 70, 80);
5158 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5159 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5161 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5162 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5164 hr = IDirect3DDevice9_GetViewport(device, &vp);
5165 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5166 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5167 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5168 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5169 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5170 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5171 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5173 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5174 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5175 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5176 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5178 IDirect3DSurface9_Release(rt);
5179 refcount = IDirect3DDevice9_Release(device);
5180 ok(!refcount, "Device has %u references left.\n", refcount);
5181 IDirect3D9_Release(d3d9);
5182 DestroyWindow(window);
5185 static void test_volume_get_container(void)
5187 IDirect3DVolumeTexture9 *texture = NULL;
5188 IDirect3DVolume9 *volume = NULL;
5189 IDirect3DDevice9 *device;
5190 IUnknown *container;
5191 IDirect3D9 *d3d9;
5192 ULONG refcount;
5193 D3DCAPS9 caps;
5194 HWND window;
5195 HRESULT hr;
5197 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5198 0, 0, 640, 480, 0, 0, 0, 0);
5199 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5200 ok(!!d3d9, "Failed to create a D3D object.\n");
5201 if (!(device = create_device(d3d9, window, NULL)))
5203 skip("Failed to create a D3D device, skipping tests.\n");
5204 IDirect3D9_Release(d3d9);
5205 DestroyWindow(window);
5206 return;
5209 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5210 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5211 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5213 skip("No volume texture support, skipping tests.\n");
5214 IDirect3DDevice9_Release(device);
5215 IDirect3D9_Release(d3d9);
5216 DestroyWindow(window);
5217 return;
5220 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5221 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5222 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5223 ok(!!texture, "Got unexpected texture %p.\n", texture);
5225 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5226 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5227 ok(!!volume, "Got unexpected volume %p.\n", volume);
5229 /* These should work... */
5230 container = NULL;
5231 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5232 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5233 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5234 IUnknown_Release(container);
5236 container = NULL;
5237 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5238 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5239 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5240 IUnknown_Release(container);
5242 container = NULL;
5243 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5244 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5245 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5246 IUnknown_Release(container);
5248 container = NULL;
5249 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5250 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5251 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5252 IUnknown_Release(container);
5254 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5255 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5256 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5257 ok(!container, "Got unexpected container %p.\n", container);
5259 IDirect3DVolume9_Release(volume);
5260 IDirect3DVolumeTexture9_Release(texture);
5261 refcount = IDirect3DDevice9_Release(device);
5262 ok(!refcount, "Device has %u references left.\n", refcount);
5263 IDirect3D9_Release(d3d9);
5264 DestroyWindow(window);
5267 static void test_volume_resource(void)
5269 IDirect3DVolumeTexture9 *texture;
5270 IDirect3DResource9 *resource;
5271 IDirect3DVolume9 *volume;
5272 IDirect3DDevice9 *device;
5273 IDirect3D9 *d3d9;
5274 ULONG refcount;
5275 D3DCAPS9 caps;
5276 HWND window;
5277 HRESULT hr;
5279 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5280 0, 0, 640, 480, 0, 0, 0, 0);
5281 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5282 ok(!!d3d9, "Failed to create a D3D object.\n");
5283 if (!(device = create_device(d3d9, window, NULL)))
5285 skip("Failed to create a D3D device, skipping tests.\n");
5286 IDirect3D9_Release(d3d9);
5287 DestroyWindow(window);
5288 return;
5291 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5292 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5293 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5295 skip("No volume texture support, skipping tests.\n");
5296 IDirect3DDevice9_Release(device);
5297 IDirect3D9_Release(d3d9);
5298 DestroyWindow(window);
5299 return;
5302 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5303 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5304 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5305 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5306 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5307 IDirect3DVolumeTexture9_Release(texture);
5309 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5310 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5312 IDirect3DVolume9_Release(volume);
5313 refcount = IDirect3DDevice9_Release(device);
5314 ok(!refcount, "Device has %u references left.\n", refcount);
5315 IDirect3D9_Release(d3d9);
5316 DestroyWindow(window);
5319 static void test_vb_lock_flags(void)
5321 static const struct
5323 DWORD flags;
5324 const char *debug_string;
5325 HRESULT win7_result;
5327 test_data[] =
5329 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5330 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5331 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5332 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5333 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5334 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5335 /* Completely bogus flags aren't an error. */
5336 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5338 IDirect3DVertexBuffer9 *buffer;
5339 IDirect3DDevice9 *device;
5340 IDirect3D9 *d3d9;
5341 unsigned int i;
5342 ULONG refcount;
5343 HWND window;
5344 HRESULT hr;
5345 void *data;
5347 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5348 0, 0, 640, 480, 0, 0, 0, 0);
5349 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5350 ok(!!d3d9, "Failed to create a D3D object.\n");
5351 if (!(device = create_device(d3d9, window, NULL)))
5353 skip("Failed to create a D3D device, skipping tests.\n");
5354 IDirect3D9_Release(d3d9);
5355 DestroyWindow(window);
5356 return;
5359 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5360 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5362 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5364 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5365 /* Windows XP always returns D3D_OK even with flags that don't make
5366 * sense. Windows 7 returns an error. At least one game (Shaiya)
5367 * depends on the Windows XP result, so mark the Windows 7 behavior as
5368 * broken. */
5369 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5370 hr, test_data[i].debug_string);
5371 if (SUCCEEDED(hr))
5373 ok(!!data, "Got unexpected data %p.\n", data);
5374 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5375 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5379 IDirect3DVertexBuffer9_Release(buffer);
5380 refcount = IDirect3DDevice9_Release(device);
5381 ok(!refcount, "Device has %u references left.\n", refcount);
5382 IDirect3D9_Release(d3d9);
5383 DestroyWindow(window);
5386 static const char *debug_d3dpool(D3DPOOL pool)
5388 switch (pool)
5390 case D3DPOOL_DEFAULT:
5391 return "D3DPOOL_DEFAULT";
5392 case D3DPOOL_SYSTEMMEM:
5393 return "D3DPOOL_SYSTEMMEM";
5394 case D3DPOOL_SCRATCH:
5395 return "D3DPOOL_SCRATCH";
5396 case D3DPOOL_MANAGED:
5397 return "D3DPOOL_MANAGED";
5398 default:
5399 return "unknown pool";
5403 static void test_vertex_buffer_alignment(void)
5405 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5406 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5407 IDirect3DVertexBuffer9 *buffer = NULL;
5408 const unsigned int align = 16;
5409 IDirect3DDevice9 *device;
5410 unsigned int i, j;
5411 IDirect3D9 *d3d9;
5412 ULONG refcount;
5413 HWND window;
5414 HRESULT hr;
5415 void *data;
5417 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5418 0, 0, 640, 480, 0, 0, 0, 0);
5419 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5420 ok(!!d3d9, "Failed to create a D3D object.\n");
5421 if (!(device = create_device(d3d9, window, NULL)))
5423 skip("Failed to create a D3D device, skipping tests.\n");
5424 IDirect3D9_Release(d3d9);
5425 DestroyWindow(window);
5426 return;
5429 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
5431 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5433 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5434 if (pools[j] == D3DPOOL_SCRATCH)
5435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5436 else
5437 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5438 debug_d3dpool(pools[j]), sizes[i], hr);
5439 if (FAILED(hr))
5440 continue;
5442 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5443 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5444 ok(!((DWORD_PTR)data & (align - 1)),
5445 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5446 data, align, sizes[i], debug_d3dpool(pools[j]));
5447 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5448 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5449 IDirect3DVertexBuffer9_Release(buffer);
5453 refcount = IDirect3DDevice9_Release(device);
5454 ok(!refcount, "Device has %u references left.\n", refcount);
5455 IDirect3D9_Release(d3d9);
5456 DestroyWindow(window);
5459 static void test_query_support(void)
5461 static const D3DQUERYTYPE queries[] =
5463 D3DQUERYTYPE_VCACHE,
5464 D3DQUERYTYPE_RESOURCEMANAGER,
5465 D3DQUERYTYPE_VERTEXSTATS,
5466 D3DQUERYTYPE_EVENT,
5467 D3DQUERYTYPE_OCCLUSION,
5468 D3DQUERYTYPE_TIMESTAMP,
5469 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5470 D3DQUERYTYPE_TIMESTAMPFREQ,
5471 D3DQUERYTYPE_PIPELINETIMINGS,
5472 D3DQUERYTYPE_INTERFACETIMINGS,
5473 D3DQUERYTYPE_VERTEXTIMINGS,
5474 D3DQUERYTYPE_PIXELTIMINGS,
5475 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5476 D3DQUERYTYPE_CACHEUTILIZATION,
5478 IDirect3DQuery9 *query = NULL;
5479 IDirect3DDevice9 *device;
5480 IDirect3D9 *d3d9;
5481 unsigned int i;
5482 ULONG refcount;
5483 BOOL supported;
5484 HWND window;
5485 HRESULT hr;
5487 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5488 0, 0, 640, 480, 0, 0, 0, 0);
5489 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5490 ok(!!d3d9, "Failed to create a D3D object.\n");
5491 if (!(device = create_device(d3d9, window, NULL)))
5493 skip("Failed to create a D3D device, skipping tests.\n");
5494 IDirect3D9_Release(d3d9);
5495 DestroyWindow(window);
5496 return;
5499 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
5501 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5502 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5504 supported = hr == D3D_OK;
5506 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5507 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5509 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5510 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5512 if (query)
5514 IDirect3DQuery9_Release(query);
5515 query = NULL;
5519 refcount = IDirect3DDevice9_Release(device);
5520 ok(!refcount, "Device has %u references left.\n", refcount);
5521 IDirect3D9_Release(d3d9);
5522 DestroyWindow(window);
5525 static void test_occlusion_query(void)
5527 static const float quad[] =
5529 -1.0f, -1.0f, 0.0f,
5530 -1.0f, 1.0f, 0.0f,
5531 1.0f, 1.0f, 0.0f,
5532 1.0f, -1.0f, 0.0f,
5534 unsigned int data_size, i, count;
5535 struct device_desc device_desc;
5536 IDirect3DQuery9 *query = NULL;
5537 IDirect3DDevice9 *device;
5538 IDirect3DSurface9 *rt;
5539 IDirect3D9 *d3d9;
5540 D3DVIEWPORT9 vp;
5541 ULONG refcount;
5542 D3DCAPS9 caps;
5543 HWND window;
5544 HRESULT hr;
5545 union
5547 WORD word[4];
5548 DWORD dword[2];
5549 UINT64 uint;
5550 } data, expected;
5551 BOOL broken_occlusion = FALSE;
5552 expected.uint = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5554 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5555 0, 0, 640, 480, 0, 0, 0, 0);
5556 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5557 ok(!!d3d9, "Failed to create a D3D object.\n");
5558 device_desc.device_window = window;
5559 device_desc.width = registry_mode.dmPelsWidth;
5560 device_desc.height = registry_mode.dmPelsHeight;
5561 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5562 if (!(device = create_device(d3d9, window, &device_desc)))
5564 skip("Failed to create a D3D device, skipping tests.\n");
5565 IDirect3D9_Release(d3d9);
5566 DestroyWindow(window);
5567 return;
5570 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5571 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5572 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5573 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5574 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5575 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5577 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5578 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5579 if (!query)
5581 skip("Occlusion queries are not supported, skipping tests.\n");
5582 IDirect3DDevice9_Release(device);
5583 IDirect3D9_Release(d3d9);
5584 DestroyWindow(window);
5585 return;
5588 data_size = IDirect3DQuery9_GetDataSize(query);
5589 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5591 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5592 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5593 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5594 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5596 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5597 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5598 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5599 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5600 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5601 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5603 data.dword[0] = 0x12345678;
5604 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5605 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5606 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5607 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5608 if (hr == D3D_OK)
5609 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5611 hr = IDirect3DDevice9_BeginScene(device);
5612 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5613 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5614 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5615 hr = IDirect3DDevice9_EndScene(device);
5616 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5618 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5619 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5620 for (i = 0; i < 500; ++i)
5622 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5623 break;
5624 Sleep(10);
5626 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5628 memset(&data, 0xff, sizeof(data));
5629 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5630 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5631 ok(data.dword[0] == expected.dword[0] || broken(!data.dword[0]),
5632 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5633 if (!data.dword[0])
5635 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5636 broken_occlusion = TRUE;
5639 memset(&data, 0xff, sizeof(data));
5640 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5641 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5642 if (!broken_occlusion)
5643 ok(data.word[0] == expected.word[0],
5644 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5645 ok(data.word[1] == 0xffff,
5646 "data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5648 memset(&data, 0xf0, sizeof(data));
5649 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5650 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5651 if (!broken_occlusion)
5652 ok(data.dword[0] == expected.dword[0],
5653 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5654 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5655 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5656 on AMD and Nvidia respectively). */
5657 if (0)
5659 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5660 data.dword[1]);
5663 memset(&data, 0xff, sizeof(data));
5664 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5665 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5666 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5668 /* This crashes on Windows. */
5669 if (0)
5671 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5672 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5675 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5676 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5677 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5678 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5679 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5680 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5682 if (broken_occlusion)
5683 goto done;
5685 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5686 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5688 vp.X = 0;
5689 vp.Y = 0;
5690 vp.Width = min(caps.MaxTextureWidth, 8192);
5691 vp.Height = min(caps.MaxTextureHeight, 8192);
5692 vp.MinZ = 0.0f;
5693 vp.MaxZ = 1.0f;
5694 hr = IDirect3DDevice9_SetViewport(device, &vp);
5695 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5697 hr = IDirect3DDevice9_CreateRenderTarget(device, vp.Width, vp.Height,
5698 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5699 if (FAILED(hr))
5701 skip("Failed to create render target (width %u, height %u), hr %#x.\n", vp.Width, vp.Height, hr);
5702 goto done;
5704 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5705 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5706 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5707 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
5708 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5710 expected.uint = vp.Width * vp.Height;
5711 count = ((((UINT64)~0u) + 1) / expected.uint) + 1;
5712 expected.uint *= count;
5714 trace("Expects 0x%08x%08x samples.\n", expected.dword[1], expected.dword[0]);
5716 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5717 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5718 hr = IDirect3DDevice9_BeginScene(device);
5719 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5720 for (i = 0; i < count; i++)
5722 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5723 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5725 hr = IDirect3DDevice9_EndScene(device);
5726 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5727 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5728 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5730 for (i = 0; i < 500; ++i)
5732 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5733 break;
5734 Sleep(10);
5736 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5738 memset(&data, 0xff, sizeof(data));
5739 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5740 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5741 ok((data.dword[0] == expected.dword[0] && data.dword[1] == expected.dword[1])
5742 || (data.dword[0] == 0xffffffff && !data.dword[1])
5743 || broken(data.dword[0] < 0xffffffff && !data.dword[1]),
5744 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5746 IDirect3DSurface9_Release(rt);
5748 done:
5749 IDirect3DQuery9_Release(query);
5750 refcount = IDirect3DDevice9_Release(device);
5751 ok(!refcount, "Device has %u references left.\n", refcount);
5752 IDirect3D9_Release(d3d9);
5753 DestroyWindow(window);
5756 static void test_timestamp_query(void)
5758 static const float quad[] =
5760 -1.0f, -1.0f, 0.0f,
5761 -1.0f, 1.0f, 0.0f,
5762 1.0f, 1.0f, 0.0f,
5763 1.0f, -1.0f, 0.0f,
5765 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5766 unsigned int data_size, i;
5767 IDirect3DDevice9 *device;
5768 IDirect3D9 *d3d9;
5769 ULONG refcount;
5770 HWND window;
5771 HRESULT hr;
5772 DWORD timestamp[2], freq[2];
5773 WORD disjoint[2];
5775 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5776 0, 0, 640, 480, 0, 0, 0, 0);
5777 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5778 ok(!!d3d9, "Failed to create a D3D object.\n");
5779 if (!(device = create_device(d3d9, window, NULL)))
5781 skip("Failed to create a D3D device, skipping tests.\n");
5782 IDirect3D9_Release(d3d9);
5783 DestroyWindow(window);
5784 return;
5787 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5788 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5789 if (FAILED(hr))
5791 skip("Timestamp queries are not supported, skipping tests.\n");
5792 IDirect3DDevice9_Release(device);
5793 IDirect3D9_Release(d3d9);
5794 DestroyWindow(window);
5795 return;
5797 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5798 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5800 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5801 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5802 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5803 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5805 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
5806 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5807 data_size = IDirect3DQuery9_GetDataSize(query);
5808 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5810 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
5811 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5812 for (i = 0; i < 500; ++i)
5814 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5815 break;
5816 Sleep(10);
5818 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5820 memset(freq, 0xff, sizeof(freq));
5821 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5822 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5823 ok(freq[1] == 0xffffffff,
5824 "freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
5825 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
5826 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5827 ok(freq[1] != 0xffffffff, "high bytes of freq were not modified (0x%.8x).\n",
5828 freq[1]);
5830 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5831 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5832 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5833 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5835 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5836 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5837 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5838 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5839 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5840 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5842 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5843 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5845 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5846 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5847 hr = IDirect3DDevice9_BeginScene(device);
5848 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5849 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5850 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5851 hr = IDirect3DDevice9_EndScene(device);
5852 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5854 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5855 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5856 for (i = 0; i < 500; ++i)
5858 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5859 break;
5860 Sleep(10);
5862 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5864 memset(timestamp, 0xff, sizeof(timestamp));
5865 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5866 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5867 ok(timestamp[1] == 0xffffffff,
5868 "timestamp was modified outside of the expected size (0x%.8x).\n",
5869 timestamp[1]);
5871 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5872 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5873 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5874 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5875 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5876 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5878 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5879 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5880 for (i = 0; i < 500; ++i)
5882 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5883 break;
5884 Sleep(10);
5886 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5888 memset(disjoint, 0xff, sizeof(disjoint));
5889 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5890 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5891 ok(disjoint[1] == 0xffff,
5892 "disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
5893 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
5894 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5895 ok(disjoint[1] != 0xffff, "high bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
5897 /* It's not strictly necessary for the TIMESTAMP query to be inside
5898 * a TIMESTAMP_DISJOINT query. */
5899 hr = IDirect3DDevice9_BeginScene(device);
5900 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5901 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5902 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5903 hr = IDirect3DDevice9_EndScene(device);
5904 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5906 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5907 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5908 for (i = 0; i < 500; ++i)
5910 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5911 break;
5912 Sleep(10);
5914 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5915 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5916 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5918 IDirect3DQuery9_Release(query);
5919 IDirect3DQuery9_Release(disjoint_query);
5920 IDirect3DQuery9_Release(freq_query);
5921 refcount = IDirect3DDevice9_Release(device);
5922 ok(!refcount, "Device has %u references left.\n", refcount);
5923 IDirect3D9_Release(d3d9);
5924 DestroyWindow(window);
5927 static void test_get_set_vertex_shader(void)
5929 IDirect3DVertexShader9 *current_shader = NULL;
5930 IDirect3DVertexShader9 *shader = NULL;
5931 const IDirect3DVertexShader9Vtbl *shader_vtbl;
5932 IDirect3DDevice9 *device;
5933 ULONG refcount, i;
5934 IDirect3D9 *d3d;
5935 D3DCAPS9 caps;
5936 HWND window;
5937 HRESULT hr;
5939 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5940 0, 0, 640, 480, 0, 0, 0, 0);
5941 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5942 ok(!!d3d, "Failed to create a D3D object.\n");
5943 if (!(device = create_device(d3d, window, NULL)))
5945 skip("Failed to create a D3D device, skipping tests.\n");
5946 IDirect3D9_Release(d3d);
5947 DestroyWindow(window);
5948 return;
5951 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5952 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5953 if (!(caps.VertexShaderVersion & 0xffff))
5955 skip("No vertex shader support, skipping tests.\n");
5956 IDirect3DDevice9_Release(device);
5957 IDirect3D9_Release(d3d);
5958 DestroyWindow(window);
5959 return;
5962 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
5963 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5964 ok(!!shader, "Got unexpected shader %p.\n", shader);
5966 /* SetVertexShader() should not touch the shader's refcount. */
5967 i = get_refcount((IUnknown *)shader);
5968 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5969 refcount = get_refcount((IUnknown *)shader);
5970 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5971 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5973 /* GetVertexShader() should increase the shader's refcount by one. */
5974 i = refcount + 1;
5975 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
5976 refcount = get_refcount((IUnknown *)shader);
5977 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
5978 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5979 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
5980 IDirect3DVertexShader9_Release(current_shader);
5982 /* SetVertexShader() with a bogus shader vtbl */
5983 shader_vtbl = shader->lpVtbl;
5984 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
5985 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5986 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5987 shader->lpVtbl = NULL;
5988 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5989 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5990 shader->lpVtbl = shader_vtbl;
5992 IDirect3DVertexShader9_Release(shader);
5993 refcount = IDirect3DDevice9_Release(device);
5994 ok(!refcount, "Device has %u references left.\n", refcount);
5995 IDirect3D9_Release(d3d);
5996 DestroyWindow(window);
5999 static void test_vertex_shader_constant(void)
6001 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};
6002 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6003 IDirect3DDevice9 *device;
6004 IDirect3D9 *d3d;
6005 ULONG refcount;
6006 D3DCAPS9 caps;
6007 DWORD consts;
6008 HWND window;
6009 HRESULT hr;
6011 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6012 0, 0, 640, 480, 0, 0, 0, 0);
6013 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6014 ok(!!d3d, "Failed to create a D3D object.\n");
6015 if (!(device = create_device(d3d, window, NULL)))
6017 skip("Failed to create a D3D device, skipping tests.\n");
6018 IDirect3D9_Release(d3d);
6019 DestroyWindow(window);
6020 return;
6023 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6024 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6025 if (!(caps.VertexShaderVersion & 0xffff))
6027 skip("No vertex shader support, skipping tests.\n");
6028 IDirect3DDevice9_Release(device);
6029 IDirect3D9_Release(d3d);
6030 DestroyWindow(window);
6031 return;
6033 consts = caps.MaxVertexShaderConst;
6035 /* A simple check that the stuff works at all. */
6036 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
6037 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6039 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
6040 * consts from MAX - 1. */
6041 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
6042 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6043 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6044 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6045 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6046 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6047 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6048 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6050 /* Constant -1. */
6051 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
6052 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6054 refcount = IDirect3DDevice9_Release(device);
6055 ok(!refcount, "Device has %u references left.\n", refcount);
6056 IDirect3D9_Release(d3d);
6057 DestroyWindow(window);
6060 static void test_get_set_pixel_shader(void)
6062 IDirect3DPixelShader9 *current_shader = NULL;
6063 IDirect3DPixelShader9 *shader = NULL;
6064 const IDirect3DPixelShader9Vtbl *shader_vtbl;
6065 IDirect3DDevice9 *device;
6066 ULONG refcount, i;
6067 IDirect3D9 *d3d;
6068 D3DCAPS9 caps;
6069 HWND window;
6070 HRESULT hr;
6072 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6073 0, 0, 640, 480, 0, 0, 0, 0);
6074 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6075 ok(!!d3d, "Failed to create a D3D object.\n");
6076 if (!(device = create_device(d3d, window, NULL)))
6078 skip("Failed to create a D3D device, skipping tests.\n");
6079 IDirect3D9_Release(d3d);
6080 DestroyWindow(window);
6081 return;
6084 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6085 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6086 if (!(caps.PixelShaderVersion & 0xffff))
6088 skip("No pixel shader support, skipping tests.\n");
6089 IDirect3DDevice9_Release(device);
6090 IDirect3D9_Release(d3d);
6091 DestroyWindow(window);
6092 return;
6095 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
6096 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6097 ok(!!shader, "Got unexpected shader %p.\n", shader);
6099 /* SetPixelShader() should not touch the shader's refcount. */
6100 i = get_refcount((IUnknown *)shader);
6101 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6102 refcount = get_refcount((IUnknown *)shader);
6103 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6104 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6106 /* GetPixelShader() should increase the shader's refcount by one. */
6107 i = refcount + 1;
6108 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6109 refcount = get_refcount((IUnknown *)shader);
6110 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6111 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6112 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6113 IDirect3DPixelShader9_Release(current_shader);
6115 /* SetPixelShader() with a bogus shader vtbl */
6116 shader_vtbl = shader->lpVtbl;
6117 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6118 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6119 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6120 shader->lpVtbl = NULL;
6121 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6122 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6123 shader->lpVtbl = shader_vtbl;
6125 IDirect3DPixelShader9_Release(shader);
6126 refcount = IDirect3DDevice9_Release(device);
6127 ok(!refcount, "Device has %u references left.\n", refcount);
6128 IDirect3D9_Release(d3d);
6129 DestroyWindow(window);
6132 static void test_pixel_shader_constant(void)
6134 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};
6135 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6136 IDirect3DDevice9 *device;
6137 DWORD consts = 0;
6138 IDirect3D9 *d3d;
6139 ULONG refcount;
6140 D3DCAPS9 caps;
6141 HWND window;
6142 HRESULT hr;
6144 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6145 0, 0, 640, 480, 0, 0, 0, 0);
6146 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6147 ok(!!d3d, "Failed to create a D3D object.\n");
6148 if (!(device = create_device(d3d, window, NULL)))
6150 skip("Failed to create a D3D device, skipping tests.\n");
6151 IDirect3D9_Release(d3d);
6152 DestroyWindow(window);
6153 return;
6156 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6157 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6158 if (!(caps.PixelShaderVersion & 0xffff))
6160 skip("No pixel shader support, skipping tests.\n");
6161 IDirect3DDevice9_Release(device);
6162 IDirect3D9_Release(d3d);
6163 DestroyWindow(window);
6164 return;
6167 /* A simple check that the stuff works at all. */
6168 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6169 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6171 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6172 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6173 consts = consts - 1;
6174 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6176 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6177 * pointless given the way the constant limit was determined. */
6178 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6179 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6181 /* Constant -1. */
6182 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6183 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6185 refcount = IDirect3DDevice9_Release(device);
6186 ok(!refcount, "Device has %u references left.\n", refcount);
6187 IDirect3D9_Release(d3d);
6188 DestroyWindow(window);
6191 static void test_unsupported_shaders(void)
6193 static const DWORD vs_3_0[] =
6195 0xfffe0300, /* vs_3_0 */
6196 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6197 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6198 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6199 0x0000ffff, /* end */
6202 #if 0
6203 float4 main(const float4 color : COLOR) : SV_TARGET
6205 float4 o;
6207 o = color;
6209 return o;
6211 #endif
6212 static const DWORD ps_4_0[] =
6214 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6215 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6216 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6217 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6218 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6219 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6220 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6221 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6222 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6223 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6224 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6225 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6226 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6227 0x00000000, 0x00000000, 0x00000000,
6229 #if 0
6230 vs_1_1
6231 dcl_position v0
6232 def c255, 1.0, 1.0, 1.0, 1.0
6233 add r0, v0, c255
6234 mov oPos, r0
6235 #endif
6236 static const DWORD vs_1_255[] =
6238 0xfffe0101,
6239 0x0000001f, 0x80000000, 0x900f0000,
6240 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6241 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6242 0x00000001, 0xc00f0000, 0x80e40000,
6243 0x0000ffff
6245 #if 0
6246 vs_1_1
6247 dcl_position v0
6248 def c256, 1.0, 1.0, 1.0, 1.0
6249 add r0, v0, c256
6250 mov oPos, r0
6251 #endif
6252 static const DWORD vs_1_256[] =
6254 0xfffe0101,
6255 0x0000001f, 0x80000000, 0x900f0000,
6256 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6257 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6258 0x00000001, 0xc00f0000, 0x80e40000,
6259 0x0000ffff
6261 #if 0
6262 vs_3_0
6263 dcl_position v0
6264 dcl_position o0
6265 def c256, 1.0, 1.0, 1.0, 1.0
6266 add r0, v0, c256
6267 mov o0, r0
6268 #endif
6269 static const DWORD vs_3_256[] =
6271 0xfffe0300,
6272 0x0200001f, 0x80000000, 0x900f0000,
6273 0x0200001f, 0x80000000, 0xe00f0000,
6274 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6275 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6276 0x02000001, 0xe00f0000, 0x80e40000,
6277 0x0000ffff
6279 #if 0
6280 /* This shader source generates syntax errors with the native shader assembler
6281 * due to the constant register index values.
6282 * The bytecode was modified by hand to use the intended values. */
6283 vs_3_0
6284 dcl_position v0
6285 dcl_position o0
6286 defi i16, 1, 1, 1, 1
6287 rep i16
6288 add r0, r0, v0
6289 endrep
6290 mov o0, r0
6291 #endif
6292 static const DWORD vs_3_i16[] =
6294 0xfffe0300,
6295 0x0200001f, 0x80000000, 0x900f0000,
6296 0x0200001f, 0x80000000, 0xe00f0000,
6297 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6298 0x01000026, 0xf0e40010,
6299 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6300 0x00000027,
6301 0x02000001, 0xe00f0000, 0x80e40000,
6302 0x0000ffff
6304 #if 0
6305 /* This shader source generates syntax errors with the native shader assembler
6306 * due to the constant register index values.
6307 * The bytecode was modified by hand to use the intended values. */
6308 vs_3_0
6309 dcl_position v0
6310 dcl_position o0
6311 defb b16, true
6312 mov r0, v0
6313 if b16
6314 add r0, r0, v0
6315 endif
6316 mov o0, r0
6317 #endif
6318 static const DWORD vs_3_b16[] =
6320 0xfffe0300,
6321 0x0200001f, 0x80000000, 0x900f0000,
6322 0x0200001f, 0x80000000, 0xe00f0000,
6323 0x0200002f, 0xe00f0810, 0x00000001,
6324 0x02000001, 0x800f0000, 0x90e40000,
6325 0x01000028, 0xe0e40810,
6326 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6327 0x0000002b,
6328 0x02000001, 0xe00f0000, 0x80e40000,
6329 0x0000ffff
6331 #if 0
6332 /* This shader source generates syntax errors with the native shader assembler
6333 * due to the constant register index values.
6334 * The bytecode was modified by hand to use the intended values. */
6335 ps_1_1
6336 def c8, 1.0, 1.0, 1.0, 1.0
6337 add r0, v0, c8
6338 #endif
6339 static const DWORD ps_1_8[] =
6341 0xffff0101,
6342 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6343 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6344 0x0000ffff
6346 #if 0
6347 /* This shader source generates syntax errors with the native shader assembler
6348 * due to the constant register index values.
6349 * The bytecode was modified by hand to use the intended values. */
6350 ps_2_0
6351 def c32, 1.0, 1.0, 1.0, 1.0
6352 add oC0, v0, c32
6353 #endif
6354 static const DWORD ps_2_32[] =
6356 0xffff0200,
6357 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6358 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6359 0x0000ffff
6361 #if 0
6362 /* This shader source generates syntax errors with the native shader assembler
6363 * due to the constant register index values.
6364 * The bytecode was modified by hand to use the intended values. */
6365 ps_3_0
6366 dcl_color0 v0
6367 def c224, 1.0, 1.0, 1.0, 1.0
6368 add oC0, v0, c224
6369 #endif
6370 static const DWORD ps_3_224[] =
6372 0xffff0300,
6373 0x0200001f, 0x8000000a, 0x900f0000,
6374 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6375 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6376 0x0000ffff
6378 #if 0
6379 /* This shader source generates syntax errors with the native shader assembler
6380 * due to the constant register index values.
6381 * The bytecode was modified by hand to use the intended values. */
6382 ps_2_0
6383 defb b0, true
6384 defi i0, 1, 1, 1, 1
6385 rep i0
6386 if b0
6387 add r0, r0, v0
6388 endif
6389 endrep
6390 mov oC0, r0
6391 #endif
6392 static const DWORD ps_2_0_boolint[] =
6394 0xffff0200,
6395 0x0200002f, 0xe00f0800, 0x00000001,
6396 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6397 0x01000026, 0xf0e40000,
6398 0x01000028, 0xe0e40800,
6399 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6400 0x0000002b,
6401 0x00000027,
6402 0x02000001, 0x800f0800, 0x80e40000,
6403 0x0000ffff
6406 IDirect3DVertexShader9 *vs = NULL;
6407 IDirect3DPixelShader9 *ps = NULL;
6408 IDirect3DDevice9 *device;
6409 IDirect3D9 * d3d;
6410 ULONG refcount;
6411 D3DCAPS9 caps;
6412 HWND window;
6413 HRESULT hr;
6415 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6416 0, 0, 640, 480, 0, 0, 0, 0);
6417 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6418 ok(!!d3d, "Failed to create a D3D object.\n");
6419 if (!(device = create_device(d3d, window, NULL)))
6421 skip("Failed to create a D3D device, skipping tests.\n");
6422 IDirect3D9_Release(d3d);
6423 DestroyWindow(window);
6424 return;
6427 /* These should always fail, regardless of supported shader version. */
6428 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6429 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6430 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6431 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6432 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6433 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6435 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6436 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6437 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6439 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6440 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6441 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6443 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6444 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6446 else
6448 skip("GPU supports SM2+, skipping SM1 test.\n");
6451 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6453 else
6455 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6457 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6458 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6459 IDirect3DVertexShader9_Release(vs);
6460 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6461 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6462 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6463 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6464 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6465 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6466 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6467 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6470 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6472 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6473 goto cleanup;
6475 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6476 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6477 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6478 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6479 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6480 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6481 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6482 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6483 if (ps)
6484 IDirect3DPixelShader9_Release(ps);
6486 cleanup:
6487 refcount = IDirect3DDevice9_Release(device);
6488 ok(!refcount, "Device has %u references left.\n", refcount);
6489 IDirect3D9_Release(d3d);
6490 DestroyWindow(window);
6493 /* Test the default texture stage state values */
6494 static void test_texture_stage_states(void)
6496 IDirect3DDevice9 *device;
6497 IDirect3D9 *d3d;
6498 unsigned int i;
6499 ULONG refcount;
6500 D3DCAPS9 caps;
6501 DWORD value;
6502 HWND window;
6503 HRESULT hr;
6505 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6506 0, 0, 640, 480, 0, 0, 0, 0);
6507 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6508 ok(!!d3d, "Failed to create a D3D object.\n");
6509 if (!(device = create_device(d3d, window, NULL)))
6511 skip("Failed to create a D3D device, skipping tests.\n");
6512 IDirect3D9_Release(d3d);
6513 DestroyWindow(window);
6514 return;
6517 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6518 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6520 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6522 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6523 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6524 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6525 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6526 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6527 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6528 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6529 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6530 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6531 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6532 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6533 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6534 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6535 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6536 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6537 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6538 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6539 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6540 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6541 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6542 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6543 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6544 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6545 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6546 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6547 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6548 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6549 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6550 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6551 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6552 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6553 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6554 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6555 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6556 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6557 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6558 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6559 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6560 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6561 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6562 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6563 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6564 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6565 ok(value == D3DTTFF_DISABLE,
6566 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6567 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6568 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6569 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6570 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6571 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6572 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6573 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6574 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6575 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6576 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6577 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6578 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6581 refcount = IDirect3DDevice9_Release(device);
6582 ok(!refcount, "Device has %u references left.\n", refcount);
6583 IDirect3D9_Release(d3d);
6584 DestroyWindow(window);
6587 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6589 IDirect3DCubeTexture9 *texture;
6590 IDirect3D9 *d3d;
6591 HRESULT hr;
6593 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6594 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6595 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6596 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6597 IDirect3D9_Release(d3d);
6598 if (FAILED(hr))
6600 skip("No cube mipmap generation support, skipping tests.\n");
6601 return;
6604 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6605 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6606 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6607 IDirect3DCubeTexture9_Release(texture);
6609 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6610 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6611 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6612 IDirect3DCubeTexture9_Release(texture);
6615 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6617 IDirect3DCubeTexture9 *texture;
6618 IDirect3DSurface9 *surface;
6619 D3DSURFACE_DESC desc;
6620 DWORD levels;
6621 HRESULT hr;
6622 D3DCAPS9 caps;
6624 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6625 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6626 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6627 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6629 skip("Failed to create cube texture, skipping tests.\n");
6630 return;
6633 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6634 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6635 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6636 else
6637 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6639 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6640 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6641 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6642 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6643 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6644 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6646 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6647 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6648 IDirect3DSurface9_Release(surface);
6649 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6650 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6651 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6652 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6654 IDirect3DCubeTexture9_Release(texture);
6657 static void test_cube_textures(void)
6659 IDirect3DCubeTexture9 *texture;
6660 IDirect3DDevice9 *device;
6661 IDirect3D9 *d3d;
6662 ULONG refcount;
6663 D3DCAPS9 caps;
6664 HWND window;
6665 HRESULT hr;
6667 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6668 0, 0, 640, 480, 0, 0, 0, 0);
6669 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6670 ok(!!d3d, "Failed to create a D3D object.\n");
6671 if (!(device = create_device(d3d, window, NULL)))
6673 skip("Failed to create a D3D device, skipping tests.\n");
6674 IDirect3D9_Release(d3d);
6675 DestroyWindow(window);
6676 return;
6679 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6680 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6682 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
6684 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6685 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
6686 IDirect3DCubeTexture9_Release(texture);
6687 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6688 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
6689 IDirect3DCubeTexture9_Release(texture);
6690 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6691 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
6692 IDirect3DCubeTexture9_Release(texture);
6694 else
6696 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6697 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
6698 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6699 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
6700 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6701 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
6703 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
6704 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
6705 IDirect3DCubeTexture9_Release(texture);
6707 test_cube_texture_mipmap_gen(device);
6708 test_cube_texture_levels(device);
6710 refcount = IDirect3DDevice9_Release(device);
6711 ok(!refcount, "Device has %u references left.\n", refcount);
6712 IDirect3D9_Release(d3d);
6713 DestroyWindow(window);
6716 static void test_mipmap_gen(void)
6718 D3DTEXTUREFILTERTYPE filter_type;
6719 IDirect3DTexture9 *texture;
6720 IDirect3DSurface9 *surface;
6721 IDirect3DDevice9 *device;
6722 D3DSURFACE_DESC desc;
6723 D3DLOCKED_RECT lr;
6724 IDirect3D9 *d3d;
6725 ULONG refcount;
6726 unsigned int i;
6727 DWORD levels;
6728 HWND window;
6729 HRESULT hr;
6731 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6732 ok(!!d3d, "Failed to create a D3D object.\n");
6734 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6735 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
6737 skip("No mipmap generation support, skipping tests.\n");
6738 IDirect3D9_Release(d3d);
6739 return;
6742 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6743 0, 0, 640, 480, 0, 0, 0, 0);
6744 if (!(device = create_device(d3d, window, NULL)))
6746 skip("Failed to create a D3D device, skipping tests.\n");
6747 IDirect3D9_Release(d3d);
6748 DestroyWindow(window);
6749 return;
6752 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6753 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6754 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6755 IDirect3DTexture9_Release(texture);
6757 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6758 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6759 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6761 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6762 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
6763 "Got unexpected filter_type %#x.\n", filter_type);
6764 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
6765 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6766 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
6767 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6768 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6769 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
6770 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
6771 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6773 levels = IDirect3DTexture9_GetLevelCount(texture);
6774 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6776 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
6778 surface = NULL;
6779 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
6780 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6781 if (surface)
6782 IDirect3DSurface9_Release(surface);
6784 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
6785 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6787 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
6788 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6789 if (SUCCEEDED(hr))
6791 hr = IDirect3DTexture9_UnlockRect(texture, i);
6792 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
6795 IDirect3DTexture9_Release(texture);
6797 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
6798 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6799 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6800 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
6801 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6802 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6804 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
6805 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6806 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6807 levels = IDirect3DTexture9_GetLevelCount(texture);
6808 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6809 IDirect3DTexture9_Release(texture);
6811 refcount = IDirect3DDevice9_Release(device);
6812 ok(!refcount, "Device has %u references left.\n", refcount);
6813 IDirect3D9_Release(d3d);
6814 DestroyWindow(window);
6817 static void test_filter(void)
6819 static const struct
6821 DWORD magfilter, minfilter, mipfilter;
6822 BOOL has_texture;
6823 HRESULT result;
6825 tests[] =
6827 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6828 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6829 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6830 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
6831 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
6833 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6834 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6835 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
6836 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
6838 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6839 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6840 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
6841 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
6842 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
6844 IDirect3DTexture9 *texture;
6845 IDirect3DDevice9 *device;
6846 IDirect3D9 *d3d;
6847 unsigned int i;
6848 ULONG refcount;
6849 DWORD passes;
6850 HWND window;
6851 HRESULT hr;
6853 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6854 ok(!!d3d, "Failed to create a D3D object.\n");
6856 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6857 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6859 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
6860 IDirect3D9_Release(d3d);
6861 return;
6864 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6865 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6867 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
6868 IDirect3D9_Release(d3d);
6869 return;
6872 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6873 0, 0, 640, 480, 0, 0, 0, 0);
6874 if (!(device = create_device(d3d, window, NULL)))
6876 skip("Failed to create a D3D device, skipping tests.\n");
6877 IDirect3D9_Release(d3d);
6878 DestroyWindow(window);
6879 return;
6882 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
6883 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
6884 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6886 /* Needed for ValidateDevice(). */
6887 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6888 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6890 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
6892 if (tests[i].has_texture)
6894 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
6895 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6897 else
6899 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6900 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6903 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
6904 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6905 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
6906 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6907 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
6908 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6910 passes = 0xdeadbeef;
6911 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
6912 ok(hr == tests[i].result,
6913 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
6914 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
6915 tests[i].mipfilter, tests[i].has_texture);
6916 if (SUCCEEDED(hr))
6917 ok(!!passes, "Got unexpected passes %#x.\n", passes);
6918 else
6919 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
6922 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6923 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6924 IDirect3DTexture9_Release(texture);
6926 refcount = IDirect3DDevice9_Release(device);
6927 ok(!refcount, "Device has %u references left.\n", refcount);
6928 IDirect3D9_Release(d3d);
6929 DestroyWindow(window);
6932 static void test_get_set_texture(void)
6934 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
6935 IDirect3DBaseTexture9 *texture;
6936 IDirect3DDevice9 *device;
6937 IDirect3D9 *d3d;
6938 ULONG refcount;
6939 HWND window;
6940 HRESULT hr;
6942 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6943 0, 0, 640, 480, 0, 0, 0, 0);
6944 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6945 ok(!!d3d, "Failed to create a D3D object.\n");
6946 if (!(device = create_device(d3d, window, NULL)))
6948 skip("Failed to create a D3D device, skipping tests.\n");
6949 IDirect3D9_Release(d3d);
6950 DestroyWindow(window);
6951 return;
6954 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
6955 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6956 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6957 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
6958 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6959 ok(!texture, "Got unexpected texture %p.\n", texture);
6961 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
6962 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
6963 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6964 texture_vtbl = texture->lpVtbl;
6965 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
6966 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6967 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6968 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6969 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6970 texture->lpVtbl = NULL;
6971 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6972 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6973 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6974 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6975 texture->lpVtbl = texture_vtbl;
6976 IDirect3DBaseTexture9_Release(texture);
6978 refcount = IDirect3DDevice9_Release(device);
6979 ok(!refcount, "Device has %u references left.\n", refcount);
6980 IDirect3D9_Release(d3d);
6981 DestroyWindow(window);
6984 static void test_lod(void)
6986 IDirect3DTexture9 *texture;
6987 IDirect3DDevice9 *device;
6988 IDirect3D9 *d3d;
6989 ULONG refcount;
6990 HWND window;
6991 HRESULT hr;
6992 DWORD ret;
6994 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6995 0, 0, 640, 480, 0, 0, 0, 0);
6996 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6997 ok(!!d3d, "Failed to create a D3D object.\n");
6998 if (!(device = create_device(d3d, window, NULL)))
7000 skip("Failed to create a D3D device, skipping tests.\n");
7001 IDirect3D9_Release(d3d);
7002 DestroyWindow(window);
7003 return;
7006 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
7007 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7008 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7010 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
7011 * return a HRESULT, so it can't return a normal error. Instead, the call
7012 * is simply ignored. */
7013 ret = IDirect3DTexture9_SetLOD(texture, 0);
7014 ok(!ret, "Got unexpected ret %u.\n", ret);
7015 ret = IDirect3DTexture9_SetLOD(texture, 1);
7016 ok(!ret, "Got unexpected ret %u.\n", ret);
7017 ret = IDirect3DTexture9_SetLOD(texture, 2);
7018 ok(!ret, "Got unexpected ret %u.\n", ret);
7019 ret = IDirect3DTexture9_GetLOD(texture);
7020 ok(!ret, "Got unexpected ret %u.\n", ret);
7022 IDirect3DTexture9_Release(texture);
7023 refcount = IDirect3DDevice9_Release(device);
7024 ok(!refcount, "Device has %u references left.\n", refcount);
7025 IDirect3D9_Release(d3d);
7026 DestroyWindow(window);
7029 static void test_surface_get_container(void)
7031 IDirect3DTexture9 *texture = NULL;
7032 IDirect3DSurface9 *surface = NULL;
7033 IDirect3DDevice9 *device;
7034 IUnknown *container;
7035 IDirect3D9 *d3d;
7036 ULONG refcount;
7037 HWND window;
7038 HRESULT hr;
7040 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7041 0, 0, 640, 480, 0, 0, 0, 0);
7042 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7043 ok(!!d3d, "Failed to create a D3D object.\n");
7044 if (!(device = create_device(d3d, window, NULL)))
7046 skip("Failed to create a D3D device, skipping tests.\n");
7047 IDirect3D9_Release(d3d);
7048 DestroyWindow(window);
7049 return;
7052 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
7053 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7054 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7055 ok(!!texture, "Got unexpected texture %p.\n", texture);
7057 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7058 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7059 ok(!!surface, "Got unexpected surface %p.\n", surface);
7061 /* These should work... */
7062 container = NULL;
7063 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
7064 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7065 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7066 IUnknown_Release(container);
7068 container = NULL;
7069 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
7070 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7071 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7072 IUnknown_Release(container);
7074 container = NULL;
7075 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
7076 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7077 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7078 IUnknown_Release(container);
7080 container = NULL;
7081 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
7082 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7083 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7084 IUnknown_Release(container);
7086 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
7087 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
7088 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7089 ok(!container, "Got unexpected container %p.\n", container);
7091 IDirect3DSurface9_Release(surface);
7092 IDirect3DTexture9_Release(texture);
7093 refcount = IDirect3DDevice9_Release(device);
7094 ok(!refcount, "Device has %u references left.\n", refcount);
7095 IDirect3D9_Release(d3d);
7096 DestroyWindow(window);
7099 static void test_surface_alignment(void)
7101 IDirect3DSurface9 *surface;
7102 IDirect3DDevice9 *device;
7103 D3DLOCKED_RECT lr;
7104 unsigned int i, j;
7105 IDirect3D9 *d3d;
7106 ULONG refcount;
7107 HWND window;
7108 HRESULT hr;
7110 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7111 0, 0, 640, 480, 0, 0, 0, 0);
7112 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7113 ok(!!d3d, "Failed to create a D3D object.\n");
7114 if (!(device = create_device(d3d, window, NULL)))
7116 skip("Failed to create a D3D device, skipping tests.\n");
7117 IDirect3D9_Release(d3d);
7118 DestroyWindow(window);
7119 return;
7122 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7123 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7124 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7125 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7127 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7128 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7129 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7130 /* Some applications also depend on the exact pitch, rather than just the
7131 * alignment. */
7132 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7133 hr = IDirect3DSurface9_UnlockRect(surface);
7134 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7135 IDirect3DSurface9_Release(surface);
7137 for (i = 0; i < 5; ++i)
7139 IDirect3DTexture9 *texture;
7140 unsigned int level_count;
7141 D3DSURFACE_DESC desc;
7142 int expected_pitch;
7144 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7145 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7146 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7147 if (FAILED(hr))
7149 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7150 continue;
7153 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7154 for (j = 0; j < level_count; ++j)
7156 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7157 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7158 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7159 hr = IDirect3DTexture9_UnlockRect(texture, j);
7160 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7162 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7163 if (i > 0)
7164 expected_pitch <<= 1;
7165 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7166 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7168 IDirect3DTexture9_Release(texture);
7171 refcount = IDirect3DDevice9_Release(device);
7172 ok(!refcount, "Device has %u references left.\n", refcount);
7173 IDirect3D9_Release(d3d);
7174 DestroyWindow(window);
7177 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7178 * different from regular formats. This test verifies we return the correct
7179 * memory offsets. */
7180 static void test_lockrect_offset(void)
7182 static const struct
7184 D3DFORMAT format;
7185 const char *name;
7186 unsigned int block_width;
7187 unsigned int block_height;
7188 unsigned int block_size;
7190 dxt_formats[] =
7192 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7193 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7194 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7195 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7196 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7197 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7198 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7200 unsigned int expected_offset, offset, i;
7201 const RECT rect = {60, 60, 68, 68};
7202 IDirect3DSurface9 *surface;
7203 D3DLOCKED_RECT locked_rect;
7204 IDirect3DDevice9 *device;
7205 int expected_pitch;
7206 IDirect3D9 *d3d;
7207 ULONG refcount;
7208 HWND window;
7209 BYTE *base;
7210 HRESULT hr;
7212 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7213 0, 0, 640, 480, 0, 0, 0, 0);
7214 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7215 ok(!!d3d, "Failed to create a D3D object.\n");
7216 if (!(device = create_device(d3d, window, NULL)))
7218 skip("Failed to create a D3D device, skipping tests.\n");
7219 IDirect3D9_Release(d3d);
7220 DestroyWindow(window);
7221 return;
7224 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
7226 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7227 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7229 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7230 continue;
7233 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7234 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7235 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7237 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7238 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7240 base = locked_rect.pBits;
7241 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7242 * dxt_formats[i].block_size;
7243 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7244 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7246 hr = IDirect3DSurface9_UnlockRect(surface);
7247 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7249 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7250 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7252 offset = (BYTE *)locked_rect.pBits - base;
7253 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7254 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7255 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7256 offset, dxt_formats[i].name, expected_offset);
7258 hr = IDirect3DSurface9_UnlockRect(surface);
7259 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7261 IDirect3DSurface9_Release(surface);
7264 refcount = IDirect3DDevice9_Release(device);
7265 ok(!refcount, "Device has %u references left.\n", refcount);
7266 IDirect3D9_Release(d3d);
7267 DestroyWindow(window);
7270 static void test_lockrect_invalid(void)
7272 static const struct
7274 RECT rect;
7275 HRESULT win7_result;
7277 test_data[] =
7279 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7280 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7281 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7282 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7283 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7284 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7285 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7286 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7287 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7288 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7289 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7290 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7291 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7293 static const RECT test_rect_2 = {0, 0, 8, 8};
7294 IDirect3DSurface9 *surface = NULL;
7295 D3DLOCKED_RECT locked_rect;
7296 IDirect3DDevice9 *device;
7297 IDirect3DTexture9 *texture;
7298 IDirect3DCubeTexture9 *cube_texture;
7299 HRESULT hr, expected_hr;
7300 unsigned int i, r;
7301 IDirect3D9 *d3d;
7302 ULONG refcount;
7303 HWND window;
7304 BYTE *base;
7305 static const struct
7307 D3DRESOURCETYPE type;
7308 D3DPOOL pool;
7309 const char *name;
7311 resources[] =
7313 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7314 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7315 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7316 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7317 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7318 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7319 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7322 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7323 0, 0, 640, 480, 0, 0, 0, 0);
7324 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7325 ok(!!d3d, "Failed to create a D3D object.\n");
7326 if (!(device = create_device(d3d, window, NULL)))
7328 skip("Failed to create a D3D device, skipping tests.\n");
7329 IDirect3D9_Release(d3d);
7330 DestroyWindow(window);
7331 return;
7334 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
7336 texture = NULL;
7337 cube_texture = NULL;
7338 switch (resources[r].type)
7340 case D3DRTYPE_SURFACE:
7341 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7342 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7343 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7344 hr, resources[r].name);
7345 break;
7347 case D3DRTYPE_TEXTURE:
7348 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7349 resources[r].pool, &texture, NULL);
7350 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7351 hr, resources[r].name);
7352 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7353 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7354 hr, resources[r].name);
7355 break;
7357 case D3DRTYPE_CUBETEXTURE:
7358 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7359 resources[r].pool, &cube_texture, NULL);
7360 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7361 hr, resources[r].name);
7362 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7363 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7364 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7365 hr, resources[r].name);
7366 break;
7368 default:
7369 break;
7372 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7373 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7374 base = locked_rect.pBits;
7375 hr = IDirect3DSurface9_UnlockRect(surface);
7376 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7377 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
7378 hr = IDirect3DSurface9_UnlockRect(surface);
7379 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
7381 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7383 unsigned int offset, expected_offset;
7384 const RECT *rect = &test_data[i].rect;
7386 locked_rect.pBits = (BYTE *)0xdeadbeef;
7387 locked_rect.Pitch = 0xdeadbeef;
7389 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7390 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7391 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7392 * one broken. */
7393 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7394 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7395 wine_dbgstr_rect(rect), hr, resources[r].name);
7396 if (FAILED(hr))
7397 continue;
7399 offset = (BYTE *)locked_rect.pBits - base;
7400 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7401 ok(offset == expected_offset,
7402 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7403 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7405 hr = IDirect3DSurface9_UnlockRect(surface);
7406 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7408 if (texture)
7410 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7411 ok(SUCCEEDED(hr),
7412 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7413 wine_dbgstr_rect(rect), hr, resources[r].name);
7414 if (FAILED(hr))
7415 continue;
7417 offset = (BYTE *)locked_rect.pBits - base;
7418 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7419 ok(offset == expected_offset,
7420 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7421 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7423 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7424 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7426 if (cube_texture)
7428 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7429 &locked_rect, rect, 0);
7430 ok(SUCCEEDED(hr),
7431 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7432 wine_dbgstr_rect(rect), hr, resources[r].name);
7433 if (FAILED(hr))
7434 continue;
7436 offset = (BYTE *)locked_rect.pBits - base;
7437 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7438 ok(offset == expected_offset,
7439 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7440 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7442 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7443 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7447 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7448 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7449 locked_rect.pBits = (BYTE *)0xdeadbeef;
7450 locked_rect.Pitch = 1;
7451 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7452 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7453 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7454 locked_rect.pBits, resources[r].name);
7455 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7456 locked_rect.Pitch, resources[r].name);
7457 hr = IDirect3DSurface9_UnlockRect(surface);
7458 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7460 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7461 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7462 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7463 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7464 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7465 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7466 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7467 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7468 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7469 hr = IDirect3DSurface9_UnlockRect(surface);
7470 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7472 IDirect3DSurface9_Release(surface);
7474 if (texture)
7476 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7477 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7478 hr, resources[r].name);
7479 locked_rect.pBits = (BYTE *)0xdeadbeef;
7480 locked_rect.Pitch = 1;
7481 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7482 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7483 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7484 locked_rect.pBits, resources[r].name);
7485 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7486 locked_rect.Pitch, resources[r].name);
7487 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7488 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7489 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7490 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7491 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7492 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7494 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7495 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7496 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7497 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7498 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7499 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7500 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7501 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7502 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7503 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7504 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7506 IDirect3DTexture9_Release(texture);
7508 if (cube_texture)
7510 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7511 &locked_rect, NULL, 0);
7512 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7513 hr, resources[r].name);
7514 locked_rect.pBits = (BYTE *)0xdeadbeef;
7515 locked_rect.Pitch = 1;
7516 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7517 &locked_rect, NULL, 0);
7518 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7519 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7520 locked_rect.pBits, resources[r].name);
7521 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7522 locked_rect.Pitch, resources[r].name);
7523 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7524 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7525 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7526 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7527 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7528 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7530 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7531 &locked_rect, &test_data[0].rect, 0);
7532 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7533 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7534 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7535 &locked_rect, &test_data[0].rect, 0);
7536 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7537 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7538 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7539 &locked_rect, &test_rect_2, 0);
7540 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7541 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7542 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7543 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7545 IDirect3DCubeTexture9_Release(cube_texture);
7549 refcount = IDirect3DDevice9_Release(device);
7550 ok(!refcount, "Device has %u references left.\n", refcount);
7551 IDirect3D9_Release(d3d);
7552 DestroyWindow(window);
7555 static void test_private_data(void)
7557 ULONG refcount, expected_refcount;
7558 IDirect3DTexture9 *texture;
7559 IDirect3DSurface9 *surface, *surface2;
7560 IDirect3DDevice9 *device;
7561 IDirect3D9 *d3d;
7562 IUnknown *ptr;
7563 HWND window;
7564 HRESULT hr;
7565 DWORD size;
7566 DWORD data[4] = {1, 2, 3, 4};
7567 static const GUID d3d9_private_data_test_guid2 =
7569 0x2e5afac2,
7570 0x87b5,
7571 0x4c10,
7572 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7575 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7576 0, 0, 640, 480, 0, 0, 0, 0);
7577 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7578 ok(!!d3d, "Failed to create a D3D object.\n");
7579 if (!(device = create_device(d3d, window, NULL)))
7581 skip("Failed to create a D3D device, skipping tests.\n");
7582 IDirect3D9_Release(d3d);
7583 DestroyWindow(window);
7584 return;
7587 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7588 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7589 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7591 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7592 device, 0, D3DSPD_IUNKNOWN);
7593 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7594 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7595 device, 5, D3DSPD_IUNKNOWN);
7596 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7597 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7598 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7599 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7601 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7602 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7603 sizeof(device), D3DSPD_IUNKNOWN);
7604 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7605 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7606 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7607 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7608 size = sizeof(ptr);
7609 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7610 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7611 IUnknown_Release(ptr);
7612 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7613 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7615 refcount = get_refcount((IUnknown *)device);
7616 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7617 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7618 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7619 expected_refcount = refcount + 1;
7620 refcount = get_refcount((IUnknown *)device);
7621 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7622 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7623 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7624 expected_refcount = refcount - 1;
7625 refcount = get_refcount((IUnknown *)device);
7626 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7628 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7629 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7630 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7631 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7632 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7633 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7634 refcount = get_refcount((IUnknown *)device);
7635 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7637 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7638 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7639 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7640 size = 2 * sizeof(ptr);
7641 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7642 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7643 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7644 expected_refcount = refcount + 2;
7645 refcount = get_refcount((IUnknown *)device);
7646 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7647 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
7648 IUnknown_Release(ptr);
7649 expected_refcount--;
7651 ptr = (IUnknown *)0xdeadbeef;
7652 size = 1;
7653 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7654 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7655 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7656 size = 2 * sizeof(ptr);
7657 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7658 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7659 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7660 refcount = get_refcount((IUnknown *)device);
7661 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7662 size = 1;
7663 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7664 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7665 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7666 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7667 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
7668 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7669 size = 0xdeadbabe;
7670 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
7671 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7672 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7673 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7674 /* GetPrivateData with size = NULL causes an access violation on Windows if the
7675 * requested data exists. */
7677 /* Destroying the surface frees the held reference. */
7678 IDirect3DSurface9_Release(surface);
7679 expected_refcount = refcount - 2;
7680 refcount = get_refcount((IUnknown *)device);
7681 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7683 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
7684 &texture, NULL);
7685 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7686 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7687 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
7688 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
7689 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
7691 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7692 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7694 memset(data, 0, sizeof(data));
7695 size = sizeof(data);
7696 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
7697 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7698 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
7699 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7700 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
7701 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
7703 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
7704 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7706 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7707 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7708 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
7709 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7711 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7712 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7714 IDirect3DSurface9_Release(surface2);
7715 IDirect3DSurface9_Release(surface);
7716 IDirect3DTexture9_Release(texture);
7718 refcount = IDirect3DDevice9_Release(device);
7719 ok(!refcount, "Device has %u references left.\n", refcount);
7720 IDirect3D9_Release(d3d);
7721 DestroyWindow(window);
7724 static void test_getdc(void)
7726 static const struct
7728 const char *name;
7729 D3DFORMAT format;
7730 unsigned int bit_count;
7731 DWORD mask_r, mask_g, mask_b;
7732 BOOL getdc_supported;
7734 testdata[] =
7736 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7737 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7738 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
7739 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7740 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7741 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
7742 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7743 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7744 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7745 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7746 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7747 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7748 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7749 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7750 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7751 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
7752 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7753 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7754 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7755 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7757 IDirect3DSurface9 *surface, *surface2;
7758 IDirect3DCubeTexture9 *cube_texture;
7759 IDirect3DTexture9 *texture;
7760 IDirect3DDevice9 *device;
7761 D3DLOCKED_RECT map_desc;
7762 IDirect3D9 *d3d;
7763 unsigned int i;
7764 ULONG refcount;
7765 HWND window;
7766 HDC dc, dc2;
7767 HRESULT hr;
7769 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7770 0, 0, 640, 480, 0, 0, 0, 0);
7771 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7772 ok(!!d3d, "Failed to create a D3D object.\n");
7773 if (!(device = create_device(d3d, window, NULL)))
7775 skip("Failed to create a D3D device, skipping tests.\n");
7776 IDirect3D9_Release(d3d);
7777 DestroyWindow(window);
7778 return;
7781 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
7783 texture = NULL;
7784 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7785 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
7786 if (FAILED(hr))
7788 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
7789 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
7790 if (FAILED(hr))
7792 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7793 continue;
7795 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7796 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7799 dc = (void *)0x1234;
7800 hr = IDirect3DSurface9_GetDC(surface, &dc);
7801 if (testdata[i].getdc_supported)
7802 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7803 else
7804 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7806 if (SUCCEEDED(hr))
7808 unsigned int width_bytes;
7809 DIBSECTION dib;
7810 HBITMAP bitmap;
7811 DWORD type;
7812 int size;
7814 type = GetObjectType(dc);
7815 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7816 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7817 type = GetObjectType(bitmap);
7818 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7820 size = GetObjectA(bitmap, sizeof(dib), &dib);
7821 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
7822 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
7823 dib.dsBm.bmType, testdata[i].name);
7824 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
7825 dib.dsBm.bmWidth, testdata[i].name);
7826 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
7827 dib.dsBm.bmHeight, testdata[i].name);
7828 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
7829 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
7830 dib.dsBm.bmWidthBytes, testdata[i].name);
7831 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
7832 dib.dsBm.bmPlanes, testdata[i].name);
7833 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
7834 "Got unexpected bit count %d for format %s.\n",
7835 dib.dsBm.bmBitsPixel, testdata[i].name);
7836 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
7837 dib.dsBm.bmBits, testdata[i].name);
7839 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
7840 dib.dsBmih.biSize, testdata[i].name);
7841 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
7842 dib.dsBmih.biHeight, testdata[i].name);
7843 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
7844 dib.dsBmih.biHeight, testdata[i].name);
7845 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
7846 dib.dsBmih.biPlanes, testdata[i].name);
7847 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
7848 dib.dsBmih.biBitCount, testdata[i].name);
7849 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
7850 "Got unexpected compression %#x for format %s.\n",
7851 dib.dsBmih.biCompression, testdata[i].name);
7852 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
7853 dib.dsBmih.biSizeImage, testdata[i].name);
7854 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
7855 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
7856 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
7857 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
7858 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
7859 dib.dsBmih.biClrUsed, testdata[i].name);
7860 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
7861 dib.dsBmih.biClrImportant, testdata[i].name);
7863 if (dib.dsBmih.biCompression == BI_BITFIELDS)
7865 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
7866 && dib.dsBitfields[2] == testdata[i].mask_b,
7867 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7868 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7870 else
7872 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
7873 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7874 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7876 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
7877 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
7879 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7880 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
7882 else
7884 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
7887 IDirect3DSurface9_Release(surface);
7888 if (texture)
7889 IDirect3DTexture9_Release(texture);
7891 if (!testdata[i].getdc_supported)
7892 continue;
7894 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
7895 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
7897 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7898 continue;
7901 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
7902 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7903 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
7904 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7906 hr = IDirect3DSurface9_GetDC(surface, &dc);
7907 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7908 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7909 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7910 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7911 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7912 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7913 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7915 hr = IDirect3DSurface9_GetDC(surface, &dc);
7916 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7917 dc2 = (void *)0x1234;
7918 hr = IDirect3DSurface9_GetDC(surface, &dc2);
7919 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7920 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
7921 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7922 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7923 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7924 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7926 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7927 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7928 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7929 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7930 hr = IDirect3DSurface9_UnlockRect(surface);
7931 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7932 hr = IDirect3DSurface9_UnlockRect(surface);
7933 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7935 hr = IDirect3DSurface9_GetDC(surface, &dc);
7936 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7937 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7938 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7939 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7940 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7942 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7943 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7944 hr = IDirect3DSurface9_GetDC(surface, &dc);
7945 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7946 hr = IDirect3DSurface9_UnlockRect(surface);
7947 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7949 hr = IDirect3DSurface9_GetDC(surface, &dc);
7950 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7951 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
7952 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7953 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
7954 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7955 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7956 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7958 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7959 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7960 hr = IDirect3DSurface9_GetDC(surface, &dc2);
7961 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7962 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
7963 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7964 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7965 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7967 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7968 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7969 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7970 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7971 hr = IDirect3DSurface9_UnlockRect(surface2);
7972 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7973 hr = IDirect3DSurface9_UnlockRect(surface);
7974 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7976 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7977 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7978 hr = IDirect3DSurface9_GetDC(surface, &dc);
7979 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7980 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7981 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7982 hr = IDirect3DSurface9_UnlockRect(surface);
7983 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7985 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7986 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7987 hr = IDirect3DSurface9_GetDC(surface, &dc);
7988 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7989 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7990 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7991 hr = IDirect3DSurface9_UnlockRect(surface2);
7992 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7994 hr = IDirect3DSurface9_GetDC(surface, &dc);
7995 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7996 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7997 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7998 hr = IDirect3DSurface9_UnlockRect(surface2);
7999 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8000 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8001 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8003 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8004 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8005 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8006 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8007 hr = IDirect3DSurface9_UnlockRect(surface);
8008 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8009 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8010 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8012 hr = IDirect3DSurface9_UnlockRect(surface);
8013 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8014 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8015 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8016 hr = IDirect3DSurface9_UnlockRect(surface);
8017 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8018 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8019 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8020 hr = IDirect3DSurface9_UnlockRect(surface);
8021 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8023 hr = IDirect3DSurface9_UnlockRect(surface2);
8024 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8025 hr = IDirect3DSurface9_GetDC(surface, &dc);
8026 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8027 hr = IDirect3DSurface9_UnlockRect(surface2);
8028 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8029 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8030 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8031 hr = IDirect3DSurface9_UnlockRect(surface2);
8032 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8034 IDirect3DSurface9_Release(surface2);
8035 IDirect3DSurface9_Release(surface);
8036 IDirect3DCubeTexture9_Release(cube_texture);
8039 refcount = IDirect3DDevice9_Release(device);
8040 ok(!refcount, "Device has %u references left.\n", refcount);
8041 IDirect3D9_Release(d3d);
8042 DestroyWindow(window);
8045 static void test_surface_dimensions(void)
8047 IDirect3DSurface9 *surface;
8048 IDirect3DDevice9 *device;
8049 IDirect3D9 *d3d;
8050 ULONG refcount;
8051 HWND window;
8052 HRESULT hr;
8054 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8055 0, 0, 640, 480, 0, 0, 0, 0);
8056 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8057 ok(!!d3d, "Failed to create a D3D object.\n");
8058 if (!(device = create_device(d3d, window, NULL)))
8060 skip("Failed to create a D3D device, skipping tests.\n");
8061 IDirect3D9_Release(d3d);
8062 DestroyWindow(window);
8063 return;
8066 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8067 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8068 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8069 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8070 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8071 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8073 refcount = IDirect3DDevice9_Release(device);
8074 ok(!refcount, "Device has %u references left.\n", refcount);
8075 IDirect3D9_Release(d3d);
8076 DestroyWindow(window);
8079 static void test_surface_format_null(void)
8081 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8082 IDirect3DTexture9 *texture;
8083 IDirect3DSurface9 *surface;
8084 IDirect3DSurface9 *rt, *ds;
8085 D3DLOCKED_RECT locked_rect;
8086 IDirect3DDevice9 *device;
8087 D3DSURFACE_DESC desc;
8088 IDirect3D9 *d3d;
8089 ULONG refcount;
8090 HWND window;
8091 HRESULT hr;
8093 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8094 ok(!!d3d, "Failed to create a D3D object.\n");
8096 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8097 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8098 if (hr != D3D_OK)
8100 skip("No D3DFMT_NULL support, skipping test.\n");
8101 IDirect3D9_Release(d3d);
8102 return;
8105 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8106 0, 0, 640, 480, 0, 0, 0, 0);
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 = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8116 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8117 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8119 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8120 D3DFMT_NULL, D3DFMT_D24S8);
8121 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8123 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8124 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8125 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8127 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8128 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8130 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8131 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8133 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8134 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8136 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8137 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8139 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8140 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8142 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8143 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8145 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8146 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8148 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8149 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8151 IDirect3DSurface9_Release(rt);
8152 IDirect3DSurface9_Release(ds);
8154 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8155 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8156 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8157 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8159 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8160 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8161 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8162 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8164 hr = IDirect3DSurface9_UnlockRect(surface);
8165 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8167 IDirect3DSurface9_Release(surface);
8169 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8170 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8171 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8172 IDirect3DTexture9_Release(texture);
8174 refcount = IDirect3DDevice9_Release(device);
8175 ok(!refcount, "Device has %u references left.\n", refcount);
8176 IDirect3D9_Release(d3d);
8177 DestroyWindow(window);
8180 static void test_surface_double_unlock(void)
8182 static const D3DPOOL pools[] =
8184 D3DPOOL_DEFAULT,
8185 D3DPOOL_SCRATCH,
8186 D3DPOOL_SYSTEMMEM,
8188 IDirect3DSurface9 *surface;
8189 IDirect3DDevice9 *device;
8190 D3DLOCKED_RECT lr;
8191 IDirect3D9 *d3d;
8192 unsigned int i;
8193 ULONG refcount;
8194 HWND window;
8195 HRESULT hr;
8197 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8198 0, 0, 640, 480, 0, 0, 0, 0);
8199 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8200 ok(!!d3d, "Failed to create a D3D object.\n");
8201 if (!(device = create_device(d3d, window, NULL)))
8203 skip("Failed to create a D3D device, skipping tests.\n");
8204 IDirect3D9_Release(d3d);
8205 DestroyWindow(window);
8206 return;
8209 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
8211 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8212 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8213 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8215 hr = IDirect3DSurface9_UnlockRect(surface);
8216 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8217 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8218 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8219 hr = IDirect3DSurface9_UnlockRect(surface);
8220 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8221 hr = IDirect3DSurface9_UnlockRect(surface);
8222 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8224 IDirect3DSurface9_Release(surface);
8227 refcount = IDirect3DDevice9_Release(device);
8228 ok(!refcount, "Device has %u references left.\n", refcount);
8229 IDirect3D9_Release(d3d);
8230 DestroyWindow(window);
8233 static void test_surface_blocks(void)
8235 static const struct
8237 D3DFORMAT fmt;
8238 const char *name;
8239 unsigned int block_width;
8240 unsigned int block_height;
8241 BOOL broken;
8242 BOOL create_size_checked, core_fmt;
8244 formats[] =
8246 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8247 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8248 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8249 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8250 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8251 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8252 * which doesn't match the format spec. On newer Nvidia cards
8253 * they have the correct 4x4 block size */
8254 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8255 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8256 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8257 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8259 static const struct
8261 D3DPOOL pool;
8262 const char *name;
8263 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8264 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8265 BOOL success;
8267 pools[] =
8269 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8270 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8271 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8272 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8274 static struct
8276 D3DRESOURCETYPE rtype;
8277 const char *type_name;
8278 D3DPOOL pool;
8279 const char *pool_name;
8280 BOOL need_driver_support, need_runtime_support;
8282 create_tests[] =
8284 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8285 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8286 /* Managed offscreen plain surfaces are not supported */
8287 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8289 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8290 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8291 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8292 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8294 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8295 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8296 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8297 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8299 IDirect3DTexture9 *texture;
8300 IDirect3DCubeTexture9 *cube_texture;
8301 IDirect3DSurface9 *surface;
8302 D3DLOCKED_RECT locked_rect;
8303 IDirect3DDevice9 *device;
8304 unsigned int i, j, k, w, h;
8305 BOOL surface_only;
8306 IDirect3D9 *d3d;
8307 ULONG refcount;
8308 HWND window;
8309 HRESULT hr;
8310 RECT rect;
8311 BOOL tex_pow2, cube_pow2;
8312 D3DCAPS9 caps;
8313 static const RECT invalid[] =
8315 {60, 60, 60, 68}, /* 0 height */
8316 {60, 60, 68, 60}, /* 0 width */
8317 {68, 60, 60, 68}, /* left > right */
8318 {60, 68, 68, 60}, /* top > bottom */
8319 {-8, 60, 0, 68}, /* left < surface */
8320 {60, -8, 68, 0}, /* top < surface */
8321 {-16, 60, -8, 68}, /* right < surface */
8322 {60, -16, 68, -8}, /* bottom < surface */
8323 {60, 60, 136, 68}, /* right > surface */
8324 {60, 60, 68, 136}, /* bottom > surface */
8325 {136, 60, 144, 68}, /* left > surface */
8326 {60, 136, 68, 144}, /* top > surface */
8329 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8330 0, 0, 640, 480, 0, 0, 0, 0);
8331 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8332 ok(!!d3d, "Failed to create a D3D object.\n");
8333 if (!(device = create_device(d3d, window, NULL)))
8335 skip("Failed to create a D3D device, skipping tests.\n");
8336 IDirect3D9_Release(d3d);
8337 DestroyWindow(window);
8338 return;
8341 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8342 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8343 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8344 if (tex_pow2)
8345 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8346 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8348 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
8350 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8352 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8353 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8354 tex_support = SUCCEEDED(hr);
8355 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8356 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8357 cube_support = SUCCEEDED(hr);
8358 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8359 0, D3DRTYPE_SURFACE, formats[i].fmt);
8360 surface_support = SUCCEEDED(hr);
8362 /* Scratch pool in general allows texture creation even if the driver does
8363 * not support the format. If the format is an extension format that is not
8364 * known to the runtime, like ATI2N, some driver support is required for
8365 * this to work.
8367 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8368 * about ATI2N. I cannot check this because all my Vista+ machines support
8369 * ATI2N in hardware, but none of my WinXP machines do. */
8370 format_known = tex_support || cube_support || surface_support;
8372 for (w = 1; w <= 8; w++)
8374 for (h = 1; h <= 8; h++)
8376 BOOL block_aligned = TRUE;
8377 BOOL size_is_pow2;
8379 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8380 block_aligned = FALSE;
8382 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8384 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
8386 BOOL support, pow2;
8387 HRESULT expect_hr;
8388 BOOL may_succeed = FALSE;
8389 IUnknown **check_null;
8391 if (!formats[i].core_fmt)
8393 /* AMD warns against creating ATI2N textures smaller than
8394 * the block size because the runtime cannot calculate the
8395 * correct texture size. Generalize this for all extension
8396 * formats. */
8397 if (w < formats[i].block_width || h < formats[i].block_height)
8398 continue;
8401 texture = (IDirect3DTexture9 *)0xdeadbeef;
8402 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8403 surface = (IDirect3DSurface9 *)0xdeadbeef;
8405 switch (create_tests[j].rtype)
8407 case D3DRTYPE_TEXTURE:
8408 check_null = (IUnknown **)&texture;
8409 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8410 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8411 support = tex_support;
8412 pow2 = tex_pow2;
8413 break;
8415 case D3DRTYPE_CUBETEXTURE:
8416 if (w != h)
8417 continue;
8418 check_null = (IUnknown **)&cube_texture;
8419 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8420 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8421 support = cube_support;
8422 pow2 = cube_pow2;
8423 break;
8425 case D3DRTYPE_SURFACE:
8426 check_null = (IUnknown **)&surface;
8427 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8428 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8429 support = surface_support;
8430 pow2 = FALSE;
8431 break;
8433 default:
8434 check_null = NULL;
8435 pow2 = FALSE;
8436 support = FALSE;
8437 break;
8440 if (create_tests[j].need_driver_support && !support)
8441 expect_hr = D3DERR_INVALIDCALL;
8442 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8443 expect_hr = D3DERR_INVALIDCALL;
8444 else if (formats[i].create_size_checked && !block_aligned)
8445 expect_hr = D3DERR_INVALIDCALL;
8446 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8447 expect_hr = D3DERR_INVALIDCALL;
8448 else
8449 expect_hr = D3D_OK;
8451 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8452 * does not support it. Accept scratch creation of extension formats on
8453 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8454 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8455 * support it. */
8456 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8457 may_succeed = TRUE;
8459 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8460 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8461 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8462 if (FAILED(hr))
8463 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8464 else
8465 IUnknown_Release(*check_null);
8470 surface_only = FALSE;
8471 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8472 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8473 dynamic_tex_support = SUCCEEDED(hr);
8474 if (!dynamic_tex_support)
8476 if (!surface_support)
8478 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8479 continue;
8481 surface_only = TRUE;
8484 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
8486 switch (pools[j].pool)
8488 case D3DPOOL_SYSTEMMEM:
8489 case D3DPOOL_MANAGED:
8490 if (surface_only)
8491 continue;
8492 /* Fall through */
8493 case D3DPOOL_DEFAULT:
8494 if (surface_only)
8496 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8497 formats[i].fmt, pools[j].pool, &surface, NULL);
8498 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8500 else
8502 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8503 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8504 formats[i].fmt, pools[j].pool, &texture, NULL);
8505 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8506 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8507 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8508 IDirect3DTexture9_Release(texture);
8510 break;
8512 case D3DPOOL_SCRATCH:
8513 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8514 formats[i].fmt, pools[j].pool, &surface, NULL);
8515 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8516 break;
8518 default:
8519 break;
8522 if (formats[i].block_width > 1)
8524 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8525 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8526 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8527 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8528 SUCCEEDED(hr) ? "succeeded" : "failed",
8529 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8530 if (SUCCEEDED(hr))
8532 hr = IDirect3DSurface9_UnlockRect(surface);
8533 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8536 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8537 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8538 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8539 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8540 SUCCEEDED(hr) ? "succeeded" : "failed",
8541 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8542 if (SUCCEEDED(hr))
8544 hr = IDirect3DSurface9_UnlockRect(surface);
8545 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8549 if (formats[i].block_height > 1)
8551 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
8552 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8553 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8554 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8555 SUCCEEDED(hr) ? "succeeded" : "failed",
8556 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8557 if (SUCCEEDED(hr))
8559 hr = IDirect3DSurface9_UnlockRect(surface);
8560 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8563 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
8564 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8565 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8566 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8567 SUCCEEDED(hr) ? "succeeded" : "failed",
8568 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8569 if (SUCCEEDED(hr))
8571 hr = IDirect3DSurface9_UnlockRect(surface);
8572 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8576 for (k = 0; k < sizeof(invalid) / sizeof(*invalid); ++k)
8578 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
8579 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
8580 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
8581 formats[i].name, pools[j].name, k);
8582 if (SUCCEEDED(hr))
8584 hr = IDirect3DSurface9_UnlockRect(surface);
8585 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8589 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8590 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8591 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
8592 hr = IDirect3DSurface9_UnlockRect(surface);
8593 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8595 IDirect3DSurface9_Release(surface);
8598 if (!dynamic_tex_support)
8600 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
8601 continue;
8604 if (formats[i].block_width == 1 && formats[i].block_height == 1)
8605 continue;
8606 if (!formats[i].core_fmt)
8607 continue;
8609 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
8610 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
8611 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
8613 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
8614 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8615 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8616 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8618 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
8619 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
8620 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8621 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8622 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8623 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8625 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8626 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8627 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8628 if (SUCCEEDED(hr))
8629 IDirect3DTexture9_UnlockRect(texture, 1);
8631 IDirect3DTexture9_Release(texture);
8634 refcount = IDirect3DDevice9_Release(device);
8635 ok(!refcount, "Device has %u references left.\n", refcount);
8636 IDirect3D9_Release(d3d);
8637 DestroyWindow(window);
8640 static void test_set_palette(void)
8642 IDirect3DDevice9 *device;
8643 IDirect3D9 *d3d9;
8644 UINT refcount;
8645 HWND window;
8646 HRESULT hr;
8647 PALETTEENTRY pal[256];
8648 unsigned int i;
8649 D3DCAPS9 caps;
8651 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8652 0, 0, 640, 480, 0, 0, 0, 0);
8653 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8654 ok(!!d3d9, "Failed to create a D3D object.\n");
8655 if (!(device = create_device(d3d9, window, NULL)))
8657 skip("Failed to create a D3D device, skipping tests.\n");
8658 DestroyWindow(window);
8659 return;
8662 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8664 pal[i].peRed = i;
8665 pal[i].peGreen = i;
8666 pal[i].peBlue = i;
8667 pal[i].peFlags = 0xff;
8669 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8670 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8672 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8673 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8674 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8676 pal[i].peRed = i;
8677 pal[i].peGreen = i;
8678 pal[i].peBlue = i;
8679 pal[i].peFlags = i;
8681 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
8683 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8684 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8686 else
8688 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8689 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
8692 refcount = IDirect3DDevice9_Release(device);
8693 ok(!refcount, "Device has %u references left.\n", refcount);
8694 IDirect3D9_Release(d3d9);
8695 DestroyWindow(window);
8698 static void test_swvp_buffer(void)
8700 IDirect3DDevice9 *device;
8701 IDirect3D9 *d3d9;
8702 UINT refcount;
8703 HWND window;
8704 HRESULT hr;
8705 unsigned int i;
8706 IDirect3DVertexBuffer9 *buffer;
8707 static const unsigned int bufsize = 1024;
8708 D3DVERTEXBUFFER_DESC desc;
8709 struct device_desc device_desc;
8710 struct
8712 float x, y, z;
8713 } *ptr, *ptr2;
8715 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8716 0, 0, 640, 480, 0, 0, 0, 0);
8717 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8718 ok(!!d3d9, "Failed to create a D3D object.\n");
8720 device_desc.device_window = window;
8721 device_desc.width = 640;
8722 device_desc.height = 480;
8723 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
8724 if (!(device = create_device(d3d9, window, &device_desc)))
8726 skip("Failed to create a D3D device, skipping tests.\n");
8727 DestroyWindow(window);
8728 IDirect3D9_Release(d3d9);
8729 return;
8732 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
8733 D3DPOOL_DEFAULT, &buffer, NULL);
8734 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8735 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8736 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8737 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
8738 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
8739 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
8741 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8742 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8743 for (i = 0; i < bufsize; i++)
8745 ptr[i].x = i * 1.0f;
8746 ptr[i].y = i * 2.0f;
8747 ptr[i].z = i * 3.0f;
8749 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8750 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8752 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8753 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8754 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8755 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8756 hr = IDirect3DDevice9_BeginScene(device);
8757 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8758 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8759 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8760 hr = IDirect3DDevice9_EndScene(device);
8761 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8763 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8764 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8765 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
8766 for (i = 0; i < bufsize; i++)
8768 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8770 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
8771 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8772 break;
8775 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8776 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8778 IDirect3DVertexBuffer9_Release(buffer);
8779 refcount = IDirect3DDevice9_Release(device);
8780 ok(!refcount, "Device has %u references left.\n", refcount);
8781 IDirect3D9_Release(d3d9);
8782 DestroyWindow(window);
8785 static void test_managed_buffer(void)
8787 static const unsigned int vertex_count = 1024;
8788 IDirect3DVertexBuffer9 *buffer;
8789 D3DVERTEXBUFFER_DESC desc;
8790 IDirect3DDevice9 *device;
8791 struct vec3 *ptr, *ptr2;
8792 IDirect3D9 *d3d9;
8793 unsigned int i;
8794 UINT refcount;
8795 HWND window;
8796 HRESULT hr;
8798 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8799 0, 0, 640, 480, 0, 0, 0, 0);
8800 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8801 ok(!!d3d9, "Failed to create a D3D object.\n");
8802 if (!(device = create_device(d3d9, window, NULL)))
8804 skip("Failed to create a D3D device, skipping tests.\n");
8805 IDirect3D9_Release(d3d9);
8806 DestroyWindow(window);
8807 return;
8810 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
8811 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
8812 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8813 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8814 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8815 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
8816 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
8818 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8819 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8820 for (i = 0; i < vertex_count; ++i)
8822 ptr[i].x = i * 1.0f;
8823 ptr[i].y = i * 2.0f;
8824 ptr[i].z = i * 3.0f;
8826 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8827 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8829 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8830 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8831 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8832 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8833 hr = IDirect3DDevice9_BeginScene(device);
8834 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8835 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8836 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8837 hr = IDirect3DDevice9_EndScene(device);
8838 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8840 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8841 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8842 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
8843 for (i = 0; i < vertex_count; ++i)
8845 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8847 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
8848 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8849 break;
8852 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8853 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8855 IDirect3DVertexBuffer9_Release(buffer);
8856 refcount = IDirect3DDevice9_Release(device);
8857 ok(!refcount, "Device has %u references left.\n", refcount);
8858 IDirect3D9_Release(d3d9);
8859 DestroyWindow(window);
8862 static void test_npot_textures(void)
8864 IDirect3DDevice9 *device = NULL;
8865 IDirect3D9 *d3d9;
8866 ULONG refcount;
8867 HWND window = NULL;
8868 HRESULT hr;
8869 D3DCAPS9 caps;
8870 IDirect3DTexture9 *texture;
8871 IDirect3DCubeTexture9 *cube_texture;
8872 IDirect3DVolumeTexture9 *volume_texture;
8873 struct
8875 D3DPOOL pool;
8876 const char *pool_name;
8877 HRESULT hr;
8879 pools[] =
8881 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
8882 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
8883 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
8884 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
8886 unsigned int i, levels;
8887 BOOL tex_pow2, cube_pow2, vol_pow2;
8889 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8890 0, 0, 640, 480, 0, 0, 0, 0);
8891 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8892 ok(!!d3d9, "Failed to create a D3D object.\n");
8893 if (!(device = create_device(d3d9, window, NULL)))
8895 skip("Failed to create a D3D device, skipping tests.\n");
8896 goto done;
8899 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8900 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8901 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8902 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8903 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8904 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
8905 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
8907 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
8909 for (levels = 0; levels <= 2; levels++)
8911 HRESULT expected;
8913 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
8914 pools[i].pool, &texture, NULL);
8915 if (!tex_pow2)
8917 expected = D3D_OK;
8919 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
8921 if (levels == 1)
8922 expected = D3D_OK;
8923 else
8924 expected = pools[i].hr;
8926 else
8928 expected = pools[i].hr;
8930 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
8931 pools[i].pool_name, levels, hr, expected);
8933 if (SUCCEEDED(hr))
8934 IDirect3DTexture9_Release(texture);
8937 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8938 &cube_texture, NULL);
8939 if (tex_pow2)
8941 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8942 pools[i].pool_name, hr, pools[i].hr);
8944 else
8946 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8947 pools[i].pool_name, hr, D3D_OK);
8950 if (SUCCEEDED(hr))
8951 IDirect3DCubeTexture9_Release(cube_texture);
8953 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8954 &volume_texture, NULL);
8955 if (tex_pow2)
8957 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8958 pools[i].pool_name, hr, pools[i].hr);
8960 else
8962 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8963 pools[i].pool_name, hr, D3D_OK);
8966 if (SUCCEEDED(hr))
8967 IDirect3DVolumeTexture9_Release(volume_texture);
8970 done:
8971 if (device)
8973 refcount = IDirect3DDevice9_Release(device);
8974 ok(!refcount, "Device has %u references left.\n", refcount);
8976 IDirect3D9_Release(d3d9);
8977 DestroyWindow(window);
8981 static void test_vidmem_accounting(void)
8983 IDirect3DDevice9 *device;
8984 IDirect3D9 *d3d9;
8985 ULONG refcount;
8986 HWND window;
8987 HRESULT hr = D3D_OK;
8988 IDirect3DTexture9 *textures[20];
8989 unsigned int i;
8990 UINT vidmem_start, vidmem_end, diff;
8992 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8993 0, 0, 640, 480, 0, 0, 0, 0);
8994 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8995 ok(!!d3d9, "Failed to create a D3D object.\n");
8996 if (!(device = create_device(d3d9, window, NULL)))
8998 skip("Failed to create a D3D device, skipping tests.\n");
8999 IDirect3D9_Release(d3d9);
9000 DestroyWindow(window);
9001 return;
9004 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
9005 memset(textures, 0, sizeof(textures));
9006 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
9008 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9009 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9010 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9011 * E_FAIL is returned on address space or system memory exhaustion */
9012 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9013 "Failed to create texture, hr %#x.\n", hr);
9015 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9017 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9018 diff = vidmem_start - vidmem_end;
9019 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9020 2 * i, diff / 1024 / 1024);
9022 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
9024 if (textures[i])
9025 IDirect3DTexture9_Release(textures[i]);
9028 refcount = IDirect3DDevice9_Release(device);
9029 ok(!refcount, "Device has %u references left.\n", refcount);
9030 IDirect3D9_Release(d3d9);
9031 DestroyWindow(window);
9034 static void test_volume_locking(void)
9036 IDirect3DDevice9 *device;
9037 IDirect3D9 *d3d9;
9038 HWND window;
9039 HRESULT hr;
9040 IDirect3DVolumeTexture9 *texture;
9041 unsigned int i;
9042 D3DLOCKED_BOX locked_box;
9043 ULONG refcount;
9044 D3DCAPS9 caps;
9045 static const struct
9047 D3DPOOL pool;
9048 DWORD usage;
9049 HRESULT create_hr, lock_hr;
9051 tests[] =
9053 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9054 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9055 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9056 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9057 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9058 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9059 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9060 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9063 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9064 0, 0, 640, 480, 0, 0, 0, 0);
9065 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9066 ok(!!d3d9, "Failed to create a D3D object.\n");
9067 if (!(device = create_device(d3d9, window, NULL)))
9069 skip("Failed to create a D3D device, skipping tests.\n");
9070 IDirect3D9_Release(d3d9);
9071 DestroyWindow(window);
9072 return;
9075 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9076 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9077 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9079 skip("Volume textures not supported, skipping test.\n");
9080 goto out;
9083 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9085 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9086 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9087 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9088 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9089 if (FAILED(hr))
9090 continue;
9092 locked_box.pBits = (void *)0xdeadbeef;
9093 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9094 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9095 if (SUCCEEDED(hr))
9097 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9098 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9100 else
9102 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9104 IDirect3DVolumeTexture9_Release(texture);
9107 out:
9108 refcount = IDirect3DDevice9_Release(device);
9109 ok(!refcount, "Device has %u references left.\n", refcount);
9110 IDirect3D9_Release(d3d9);
9111 DestroyWindow(window);
9114 static void test_update_volumetexture(void)
9116 IDirect3DDevice9 *device;
9117 IDirect3D9 *d3d9;
9118 HWND window;
9119 HRESULT hr;
9120 IDirect3DVolumeTexture9 *src, *dst;
9121 unsigned int i;
9122 D3DLOCKED_BOX locked_box;
9123 ULONG refcount;
9124 D3DCAPS9 caps;
9125 static const struct
9127 D3DPOOL src_pool, dst_pool;
9128 HRESULT hr;
9130 tests[] =
9132 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9133 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9134 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9135 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9137 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9138 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9139 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9140 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9142 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9143 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9144 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9145 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9147 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9148 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9149 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9150 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9152 static const struct
9154 UINT src_size, dst_size;
9155 UINT src_lvl, dst_lvl;
9156 D3DFORMAT src_fmt, dst_fmt;
9158 tests2[] =
9160 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9161 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9162 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9163 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9164 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9165 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9166 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9167 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9170 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9171 0, 0, 640, 480, 0, 0, 0, 0);
9172 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9173 ok(!!d3d9, "Failed to create a D3D object.\n");
9174 if (!(device = create_device(d3d9, window, NULL)))
9176 skip("Failed to create a D3D device, skipping tests.\n");
9177 IDirect3D9_Release(d3d9);
9178 DestroyWindow(window);
9179 return;
9182 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9183 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9184 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9186 skip("Volume textures not supported, skipping test.\n");
9187 goto out;
9190 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9192 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9193 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9195 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9196 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9197 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9198 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9199 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9200 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9202 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9203 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9204 *((DWORD *)locked_box.pBits) = 0x11223344;
9205 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9206 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9208 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9209 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9210 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9212 if (SUCCEEDED(hr))
9214 DWORD content = *((DWORD *)locked_box.pBits);
9215 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9216 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9217 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9218 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9219 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9221 IDirect3DVolumeTexture9_Release(src);
9222 IDirect3DVolumeTexture9_Release(dst);
9225 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9227 skip("Mipmapped volume maps not supported.\n");
9228 goto out;
9231 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
9233 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9234 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9235 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9236 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9237 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9238 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9239 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9240 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9242 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9243 todo_wine_if (FAILED(hr))
9244 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9246 IDirect3DVolumeTexture9_Release(src);
9247 IDirect3DVolumeTexture9_Release(dst);
9250 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9251 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9252 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9253 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9254 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9256 * I'm not adding tests for this behavior until an application needs it. */
9258 out:
9259 refcount = IDirect3DDevice9_Release(device);
9260 ok(!refcount, "Device has %u references left.\n", refcount);
9261 IDirect3D9_Release(d3d9);
9262 DestroyWindow(window);
9265 static void test_create_rt_ds_fail(void)
9267 IDirect3DDevice9 *device;
9268 HWND window;
9269 HRESULT hr;
9270 ULONG refcount;
9271 IDirect3D9 *d3d9;
9272 IDirect3DSurface9 *surface;
9274 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9275 0, 0, 640, 480, 0, 0, 0, 0);
9276 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9277 ok(!!d3d9, "Failed to create a D3D object.\n");
9278 if (!(device = create_device(d3d9, window, NULL)))
9280 skip("Failed to create a D3D device, skipping tests.\n");
9281 IDirect3D9_Release(d3d9);
9282 DestroyWindow(window);
9283 return;
9286 /* Output pointer == NULL segfaults on Windows. */
9288 surface = (IDirect3DSurface9 *)0xdeadbeef;
9289 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9290 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9291 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9292 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9293 if (SUCCEEDED(hr))
9294 IDirect3DSurface9_Release(surface);
9296 surface = (IDirect3DSurface9 *)0xdeadbeef;
9297 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9298 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9299 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9300 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9301 if (SUCCEEDED(hr))
9302 IDirect3DSurface9_Release(surface);
9304 refcount = IDirect3DDevice9_Release(device);
9305 ok(!refcount, "Device has %u references left.\n", refcount);
9306 IDirect3D9_Release(d3d9);
9307 DestroyWindow(window);
9310 static void test_volume_blocks(void)
9312 IDirect3DDevice9 *device;
9313 IDirect3D9 *d3d9;
9314 UINT refcount;
9315 HWND window;
9316 HRESULT hr;
9317 D3DCAPS9 caps;
9318 IDirect3DVolumeTexture9 *texture;
9319 unsigned int w, h, d, i, j;
9320 static const struct
9322 D3DFORMAT fmt;
9323 const char *name;
9324 unsigned int block_width;
9325 unsigned int block_height;
9326 unsigned int block_depth;
9327 unsigned int block_size;
9328 unsigned int broken;
9329 BOOL create_size_checked, core_fmt;
9331 formats[] =
9333 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9334 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9335 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9336 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9337 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9338 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9339 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9340 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9341 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9342 * which doesn't match the format spec. On newer Nvidia cards
9343 * it has the correct 4x4 block size.
9344 * ATI1N volume textures are only supported by AMD GPUs right
9345 * now and locking offsets seem just wrong. */
9346 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9347 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9348 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9349 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9351 static const struct
9353 D3DPOOL pool;
9354 const char *name;
9355 BOOL need_driver_support, need_runtime_support;
9357 create_tests[] =
9359 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9360 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9361 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9362 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9364 static const struct
9366 unsigned int x, y, z, x2, y2, z2;
9368 offset_tests[] =
9370 {0, 0, 0, 8, 8, 8},
9371 {0, 0, 3, 8, 8, 8},
9372 {0, 4, 0, 8, 8, 8},
9373 {0, 4, 3, 8, 8, 8},
9374 {4, 0, 0, 8, 8, 8},
9375 {4, 0, 3, 8, 8, 8},
9376 {4, 4, 0, 8, 8, 8},
9377 {4, 4, 3, 8, 8, 8},
9379 D3DBOX box;
9380 D3DLOCKED_BOX locked_box;
9381 BYTE *base;
9382 INT expected_row_pitch, expected_slice_pitch;
9383 BOOL support;
9384 BOOL pow2;
9385 unsigned int offset, expected_offset;
9387 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9388 0, 0, 640, 480, 0, 0, 0, 0);
9389 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9390 ok(!!d3d9, "Failed to create a D3D object.\n");
9391 if (!(device = create_device(d3d9, window, NULL)))
9393 skip("Failed to create a D3D device, skipping tests.\n");
9394 IDirect3D9_Release(d3d9);
9395 DestroyWindow(window);
9396 return;
9398 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9399 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9400 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9402 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
9404 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9405 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9406 support = SUCCEEDED(hr);
9408 /* Test creation restrictions */
9409 for (w = 1; w <= 8; w++)
9411 for (h = 1; h <= 8; h++)
9413 for (d = 1; d <= 8; d++)
9415 HRESULT expect_hr;
9416 BOOL size_is_pow2;
9417 BOOL block_aligned = TRUE;
9419 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9420 block_aligned = FALSE;
9422 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9424 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
9426 BOOL may_succeed = FALSE;
9428 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9429 expect_hr = D3DERR_INVALIDCALL;
9430 else if (formats[i].create_size_checked && !block_aligned)
9431 expect_hr = D3DERR_INVALIDCALL;
9432 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9433 expect_hr = D3DERR_INVALIDCALL;
9434 else if (create_tests[j].need_driver_support && !support)
9435 expect_hr = D3DERR_INVALIDCALL;
9436 else
9437 expect_hr = D3D_OK;
9439 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9440 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9441 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9443 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9444 * does not support it. Accept scratch creation of extension formats on
9445 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9446 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9447 * support it. */
9448 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9449 may_succeed = TRUE;
9451 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9452 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9453 hr, formats[i].name, create_tests[j].name, w, h, d);
9455 if (FAILED(hr))
9456 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9457 else
9458 IDirect3DVolumeTexture9_Release(texture);
9464 if (!support && !formats[i].core_fmt)
9465 continue;
9467 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9468 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9469 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9471 /* Test lockrect offset */
9472 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
9474 unsigned int bytes_per_pixel;
9475 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9477 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9478 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9480 base = locked_box.pBits;
9481 if (formats[i].broken == 1)
9483 expected_row_pitch = bytes_per_pixel * 24;
9485 else if (formats[i].broken == 2)
9487 expected_row_pitch = 24;
9489 else
9491 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9492 * formats[i].block_size;
9494 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9495 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9497 if (formats[i].broken)
9499 expected_slice_pitch = expected_row_pitch * 8;
9501 else
9503 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9504 * expected_row_pitch;
9506 ok(locked_box.SlicePitch == expected_slice_pitch,
9507 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9508 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9510 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9511 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9513 box.Left = offset_tests[j].x;
9514 box.Top = offset_tests[j].y;
9515 box.Front = offset_tests[j].z;
9516 box.Right = offset_tests[j].x2;
9517 box.Bottom = offset_tests[j].y2;
9518 box.Back = offset_tests[j].z2;
9519 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9520 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9522 offset = (BYTE *)locked_box.pBits - base;
9523 if (formats[i].broken == 1)
9525 expected_offset = box.Front * expected_slice_pitch
9526 + box.Top * expected_row_pitch
9527 + box.Left * bytes_per_pixel;
9529 else if (formats[i].broken == 2)
9531 expected_offset = box.Front * expected_slice_pitch
9532 + box.Top * expected_row_pitch
9533 + box.Left;
9535 else
9537 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9538 + (box.Top / formats[i].block_height) * expected_row_pitch
9539 + (box.Left / formats[i].block_width) * formats[i].block_size;
9541 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9542 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9544 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9545 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9548 /* Test partial block locks */
9549 box.Front = 0;
9550 box.Back = 1;
9551 if (formats[i].block_width > 1)
9553 box.Left = formats[i].block_width >> 1;
9554 box.Top = 0;
9555 box.Right = formats[i].block_width;
9556 box.Bottom = formats[i].block_height;
9557 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9558 ok(FAILED(hr) || broken(formats[i].broken),
9559 "Partial block lock succeeded, expected failure, format %s.\n",
9560 formats[i].name);
9561 if (SUCCEEDED(hr))
9563 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9564 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9567 box.Left = 0;
9568 box.Top = 0;
9569 box.Right = formats[i].block_width >> 1;
9570 box.Bottom = formats[i].block_height;
9571 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9572 ok(FAILED(hr) || broken(formats[i].broken),
9573 "Partial block lock succeeded, expected failure, format %s.\n",
9574 formats[i].name);
9575 if (SUCCEEDED(hr))
9577 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9578 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9582 if (formats[i].block_height > 1)
9584 box.Left = 0;
9585 box.Top = formats[i].block_height >> 1;
9586 box.Right = formats[i].block_width;
9587 box.Bottom = formats[i].block_height;
9588 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9589 ok(FAILED(hr) || broken(formats[i].broken),
9590 "Partial block lock succeeded, expected failure, format %s.\n",
9591 formats[i].name);
9592 if (SUCCEEDED(hr))
9594 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9595 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9598 box.Left = 0;
9599 box.Top = 0;
9600 box.Right = formats[i].block_width;
9601 box.Bottom = formats[i].block_height >> 1;
9602 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9603 ok(FAILED(hr) || broken(formats[i].broken),
9604 "Partial block lock succeeded, expected failure, format %s.\n",
9605 formats[i].name);
9606 if (SUCCEEDED(hr))
9608 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9609 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9613 /* Test full block lock */
9614 box.Left = 0;
9615 box.Top = 0;
9616 box.Right = formats[i].block_width;
9617 box.Bottom = formats[i].block_height;
9618 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9619 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9620 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9621 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9623 IDirect3DVolumeTexture9_Release(texture);
9625 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
9626 * does not allocate surfaces smaller than the blocksize properly. */
9627 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
9629 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
9630 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9631 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9633 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
9634 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9635 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9636 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9638 box.Left = box.Top = box.Front = 0;
9639 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
9640 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
9641 box.Back = 1;
9642 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9643 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9644 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9645 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9647 box.Right = formats[i].block_width;
9648 box.Bottom = formats[i].block_height;
9649 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9650 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9651 if (SUCCEEDED(hr))
9652 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9654 IDirect3DVolumeTexture9_Release(texture);
9658 refcount = IDirect3DDevice9_Release(device);
9659 ok(!refcount, "Device has %u references left.\n", refcount);
9660 IDirect3D9_Release(d3d9);
9661 DestroyWindow(window);
9664 static void test_lockbox_invalid(void)
9666 static const struct
9668 D3DBOX box;
9669 HRESULT result;
9671 test_data[] =
9673 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
9674 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
9675 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
9676 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
9677 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
9678 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
9679 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
9680 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
9681 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
9682 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
9683 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
9684 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
9685 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
9686 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
9688 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
9689 IDirect3DVolumeTexture9 *texture = NULL;
9690 D3DLOCKED_BOX locked_box;
9691 IDirect3DDevice9 *device;
9692 IDirect3D9 *d3d;
9693 unsigned int i;
9694 ULONG refcount;
9695 HWND window;
9696 BYTE *base;
9697 HRESULT hr;
9699 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9700 0, 0, 640, 480, 0, 0, 0, 0);
9701 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9702 ok(!!d3d, "Failed to create a D3D object.\n");
9703 if (!(device = create_device(d3d, window, NULL)))
9705 skip("Failed to create a D3D device, skipping tests.\n");
9706 IDirect3D9_Release(d3d);
9707 DestroyWindow(window);
9708 return;
9711 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
9712 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
9713 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9714 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9715 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9716 base = locked_box.pBits;
9717 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9718 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9720 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
9722 unsigned int offset, expected_offset;
9723 const D3DBOX *box = &test_data[i].box;
9725 locked_box.pBits = (BYTE *)0xdeadbeef;
9726 locked_box.RowPitch = 0xdeadbeef;
9727 locked_box.SlicePitch = 0xdeadbeef;
9729 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
9730 /* Unlike surfaces, volumes properly check the box even in Windows XP */
9731 ok(hr == test_data[i].result,
9732 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
9733 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
9734 test_data[i].result);
9735 if (FAILED(hr))
9736 continue;
9738 offset = (BYTE *)locked_box.pBits - base;
9739 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
9740 ok(offset == expected_offset,
9741 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
9742 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
9744 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9745 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9748 /* locked_box = NULL throws an exception on Windows */
9749 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9750 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9751 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9752 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9753 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9754 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9755 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9756 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9758 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9759 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9760 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9761 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9762 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9763 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9764 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9765 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9766 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
9767 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9768 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
9769 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
9770 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9771 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9773 IDirect3DVolumeTexture9_Release(texture);
9774 refcount = IDirect3DDevice9_Release(device);
9775 ok(!refcount, "Device has %u references left.\n", refcount);
9776 IDirect3D9_Release(d3d);
9777 DestroyWindow(window);
9780 static void test_shared_handle(void)
9782 IDirect3DDevice9 *device;
9783 IDirect3D9 *d3d;
9784 ULONG refcount;
9785 HWND window;
9786 HRESULT hr;
9787 /* Native d3d9ex refuses to create a shared texture if the texture pointer
9788 * is not initialized to NULL. Make sure this doesn't cause issues here. */
9789 IDirect3DTexture9 *texture = NULL;
9790 IDirect3DSurface9 *surface = NULL;
9791 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
9792 IDirect3DIndexBuffer9 *index_buffer = NULL;
9793 HANDLE handle = NULL;
9794 void *mem;
9795 D3DCAPS9 caps;
9797 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9798 0, 0, 640, 480, 0, 0, 0, 0);
9799 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9800 ok(!!d3d, "Failed to create a D3D object.\n");
9801 if (!(device = create_device(d3d, window, NULL)))
9803 skip("Failed to create a D3D device, skipping tests.\n");
9804 IDirect3D9_Release(d3d);
9805 DestroyWindow(window);
9806 return;
9809 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9810 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9811 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
9813 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
9814 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
9815 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9816 D3DPOOL_DEFAULT, &texture, &handle);
9817 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9818 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9819 D3DPOOL_SYSTEMMEM, &texture, &mem);
9820 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9822 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9823 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
9824 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9825 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9826 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
9827 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9829 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9830 &vertex_buffer, &handle);
9831 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9832 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9833 &vertex_buffer, &mem);
9834 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
9836 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9837 &index_buffer, &handle);
9838 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9839 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9840 &index_buffer, &mem);
9841 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9843 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9845 IDirect3DCubeTexture9 *cube_texture = NULL;
9846 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9847 D3DPOOL_DEFAULT, &cube_texture, &handle);
9848 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9849 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9850 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
9851 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9854 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
9856 IDirect3DVolumeTexture9 *volume_texture = NULL;
9857 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9858 D3DPOOL_DEFAULT, &volume_texture, &handle);
9859 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9860 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9861 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
9862 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9865 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
9866 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9867 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9869 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
9870 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9871 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9873 HeapFree(GetProcessHeap(), 0, mem);
9874 refcount = IDirect3DDevice9_Release(device);
9875 ok(!refcount, "Device has %u references left.\n", refcount);
9876 IDirect3D9_Release(d3d);
9877 DestroyWindow(window);
9880 static void test_pixel_format(void)
9882 HWND hwnd, hwnd2 = NULL;
9883 HDC hdc, hdc2 = NULL;
9884 HMODULE gl = NULL;
9885 int format, test_format;
9886 PIXELFORMATDESCRIPTOR pfd;
9887 IDirect3D9 *d3d9 = NULL;
9888 IDirect3DDevice9 *device = NULL;
9889 HRESULT hr;
9890 static const float point[3] = {0.0, 0.0, 0.0};
9892 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9893 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9894 if (!hwnd)
9896 skip("Failed to create window\n");
9897 return;
9900 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9901 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9903 hdc = GetDC(hwnd);
9904 if (!hdc)
9906 skip("Failed to get DC\n");
9907 goto cleanup;
9910 if (hwnd2)
9911 hdc2 = GetDC(hwnd2);
9913 gl = LoadLibraryA("opengl32.dll");
9914 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
9916 format = GetPixelFormat(hdc);
9917 ok(format == 0, "new window has pixel format %d\n", format);
9919 ZeroMemory(&pfd, sizeof(pfd));
9920 pfd.nSize = sizeof(pfd);
9921 pfd.nVersion = 1;
9922 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
9923 pfd.iPixelType = PFD_TYPE_RGBA;
9924 pfd.iLayerType = PFD_MAIN_PLANE;
9925 format = ChoosePixelFormat(hdc, &pfd);
9926 if (format <= 0)
9928 skip("no pixel format available\n");
9929 goto cleanup;
9932 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
9934 skip("failed to set pixel format\n");
9935 goto cleanup;
9938 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
9940 skip("failed to set pixel format on second window\n");
9941 if (hdc2)
9943 ReleaseDC(hwnd2, hdc2);
9944 hdc2 = NULL;
9948 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9949 ok(!!d3d9, "Failed to create a D3D object.\n");
9951 test_format = GetPixelFormat(hdc);
9952 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9954 if (!(device = create_device(d3d9, hwnd, NULL)))
9956 skip("Failed to create device\n");
9957 goto cleanup;
9960 test_format = GetPixelFormat(hdc);
9961 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9963 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9964 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
9966 test_format = GetPixelFormat(hdc);
9967 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9969 hr = IDirect3DDevice9_BeginScene(device);
9970 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
9972 test_format = GetPixelFormat(hdc);
9973 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9975 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
9976 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9978 test_format = GetPixelFormat(hdc);
9979 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9981 hr = IDirect3DDevice9_EndScene(device);
9982 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
9984 test_format = GetPixelFormat(hdc);
9985 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9987 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9988 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9990 test_format = GetPixelFormat(hdc);
9991 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9993 if (hdc2)
9995 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
9996 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9998 test_format = GetPixelFormat(hdc);
9999 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10001 test_format = GetPixelFormat(hdc2);
10002 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
10005 cleanup:
10006 if (device)
10008 UINT refcount = IDirect3DDevice9_Release(device);
10009 ok(!refcount, "Device has %u references left.\n", refcount);
10011 if (d3d9) IDirect3D9_Release(d3d9);
10012 if (gl) FreeLibrary(gl);
10013 if (hdc) ReleaseDC(hwnd, hdc);
10014 if (hdc2) ReleaseDC(hwnd2, hdc2);
10015 if (hwnd) DestroyWindow(hwnd);
10016 if (hwnd2) DestroyWindow(hwnd2);
10019 static void test_begin_end_state_block(void)
10021 IDirect3DStateBlock9 *stateblock;
10022 IDirect3DDevice9 *device;
10023 IDirect3D9 *d3d;
10024 ULONG refcount;
10025 HWND window;
10026 HRESULT hr;
10028 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10029 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10030 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10031 ok(!!d3d, "Failed to create a D3D object.\n");
10032 if (!(device = create_device(d3d, window, NULL)))
10034 skip("Failed to create a D3D device, skipping tests.\n");
10035 IDirect3D9_Release(d3d);
10036 DestroyWindow(window);
10037 return;
10040 /* Should succeed. */
10041 hr = IDirect3DDevice9_BeginStateBlock(device);
10042 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10044 /* Calling BeginStateBlock() while recording should return
10045 * D3DERR_INVALIDCALL. */
10046 hr = IDirect3DDevice9_BeginStateBlock(device);
10047 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10049 /* Should succeed. */
10050 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10051 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10052 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10053 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10054 "Got unexpected stateblock %p.\n", stateblock);
10055 IDirect3DStateBlock9_Release(stateblock);
10057 /* Calling EndStateBlock() while not recording should return
10058 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10059 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10060 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10061 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10062 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10063 "Got unexpected stateblock %p.\n", stateblock);
10065 refcount = IDirect3DDevice9_Release(device);
10066 ok(!refcount, "Device has %u references left.\n", refcount);
10067 IDirect3D9_Release(d3d);
10068 DestroyWindow(window);
10071 static void test_shader_constant_apply(void)
10073 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10074 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10075 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10076 IDirect3DStateBlock9 *stateblock;
10077 DWORD vs_version, ps_version;
10078 IDirect3DDevice9 *device;
10079 IDirect3D9 *d3d;
10080 ULONG refcount;
10081 D3DCAPS9 caps;
10082 float ret[4];
10083 HWND window;
10084 HRESULT hr;
10086 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10087 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10088 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10089 ok(!!d3d, "Failed to create a D3D object.\n");
10090 if (!(device = create_device(d3d, window, NULL)))
10092 skip("Failed to create a D3D device, skipping tests.\n");
10093 IDirect3D9_Release(d3d);
10094 DestroyWindow(window);
10095 return;
10098 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10099 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10100 vs_version = caps.VertexShaderVersion & 0xffff;
10101 ps_version = caps.PixelShaderVersion & 0xffff;
10103 if (vs_version)
10105 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10106 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10107 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10108 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10110 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10111 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10112 ok(!memcmp(ret, initial, sizeof(initial)),
10113 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10114 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10115 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10116 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10117 ok(!memcmp(ret, initial, sizeof(initial)),
10118 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10119 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10121 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10122 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10124 if (ps_version)
10126 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10127 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10128 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10129 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10131 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10132 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10133 ok(!memcmp(ret, initial, sizeof(initial)),
10134 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10135 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10136 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10137 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10138 ok(!memcmp(ret, initial, sizeof(initial)),
10139 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10140 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10142 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10143 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10146 hr = IDirect3DDevice9_BeginStateBlock(device);
10147 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10149 if (vs_version)
10151 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10152 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10154 if (ps_version)
10156 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10157 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10160 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10161 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10163 if (vs_version)
10165 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10166 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10167 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10168 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10169 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10170 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10171 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10172 ok(!memcmp(ret, initial, sizeof(initial)),
10173 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10174 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10176 if (ps_version)
10178 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10179 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10180 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10181 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10182 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10183 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10184 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10185 ok(!memcmp(ret, initial, sizeof(initial)),
10186 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10187 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10190 /* Apply doesn't overwrite constants that aren't explicitly set on the
10191 * source stateblock. */
10192 hr = IDirect3DStateBlock9_Apply(stateblock);
10193 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10195 if (vs_version)
10197 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10198 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10199 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10200 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10201 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10202 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10203 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10204 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10205 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10206 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10208 if (ps_version)
10210 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10211 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10212 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10213 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10214 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10215 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10216 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10217 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10218 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10219 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10222 IDirect3DStateBlock9_Release(stateblock);
10223 refcount = IDirect3DDevice9_Release(device);
10224 ok(!refcount, "Device has %u references left.\n", refcount);
10225 IDirect3D9_Release(d3d);
10226 DestroyWindow(window);
10229 static void test_vdecl_apply(void)
10231 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10232 IDirect3DStateBlock9 *stateblock;
10233 IDirect3DDevice9 *device;
10234 IDirect3D9 *d3d;
10235 ULONG refcount;
10236 HWND window;
10237 HRESULT hr;
10239 static const D3DVERTEXELEMENT9 decl1[] =
10241 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10242 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10243 D3DDECL_END(),
10246 static const D3DVERTEXELEMENT9 decl2[] =
10248 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10249 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10250 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10251 D3DDECL_END(),
10254 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10255 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10256 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10257 ok(!!d3d, "Failed to create a D3D object.\n");
10258 if (!(device = create_device(d3d, window, NULL)))
10260 skip("Failed to create a D3D device, skipping tests.\n");
10261 IDirect3D9_Release(d3d);
10262 DestroyWindow(window);
10263 return;
10266 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10267 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10269 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10270 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10272 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10273 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10274 hr = IDirect3DDevice9_BeginStateBlock(device);
10275 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10276 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10277 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10278 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10279 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10280 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10281 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10282 hr = IDirect3DStateBlock9_Apply(stateblock);
10283 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10284 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10285 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10286 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10287 declaration, declaration1);
10288 IDirect3DVertexDeclaration9_Release(declaration);
10290 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10291 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10292 hr = IDirect3DStateBlock9_Capture(stateblock);
10293 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10294 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10295 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10296 hr = IDirect3DStateBlock9_Apply(stateblock);
10297 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10298 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10299 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10300 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10301 declaration, declaration2);
10302 IDirect3DVertexDeclaration9_Release(declaration);
10304 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10305 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10306 hr = IDirect3DStateBlock9_Capture(stateblock);
10307 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10308 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10309 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10310 hr = IDirect3DStateBlock9_Apply(stateblock);
10311 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10312 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10313 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10314 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10315 declaration, declaration2);
10316 IDirect3DVertexDeclaration9_Release(declaration);
10318 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10319 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10320 hr = IDirect3DStateBlock9_Capture(stateblock);
10321 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10322 hr = IDirect3DStateBlock9_Apply(stateblock);
10323 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10324 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10325 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10326 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10328 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10329 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10330 hr = IDirect3DStateBlock9_Capture(stateblock);
10331 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10332 hr = IDirect3DStateBlock9_Apply(stateblock);
10333 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10334 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10335 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10336 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10337 declaration, declaration2);
10338 IDirect3DVertexDeclaration9_Release(declaration);
10340 IDirect3DStateBlock9_Release(stateblock);
10341 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10342 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10343 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10344 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10345 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10346 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10347 hr = IDirect3DStateBlock9_Apply(stateblock);
10348 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10349 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10350 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10351 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10352 declaration, declaration1);
10353 IDirect3DVertexDeclaration9_Release(declaration);
10355 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10356 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10357 hr = IDirect3DStateBlock9_Capture(stateblock);
10358 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10359 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10360 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10361 hr = IDirect3DStateBlock9_Apply(stateblock);
10362 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10363 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10364 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10365 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10366 declaration, declaration2);
10367 IDirect3DVertexDeclaration9_Release(declaration);
10369 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10370 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10371 hr = IDirect3DStateBlock9_Capture(stateblock);
10372 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10373 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10374 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10375 hr = IDirect3DStateBlock9_Apply(stateblock);
10376 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10377 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10378 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10379 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10380 declaration, declaration2);
10381 IDirect3DVertexDeclaration9_Release(declaration);
10383 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10384 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10385 hr = IDirect3DStateBlock9_Capture(stateblock);
10386 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10387 hr = IDirect3DStateBlock9_Apply(stateblock);
10388 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10389 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10390 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10391 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10393 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10394 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10395 hr = IDirect3DStateBlock9_Capture(stateblock);
10396 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10397 hr = IDirect3DStateBlock9_Apply(stateblock);
10398 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10399 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10400 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10401 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10402 declaration, declaration2);
10403 IDirect3DVertexDeclaration9_Release(declaration);
10405 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10406 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10407 IDirect3DVertexDeclaration9_Release(declaration1);
10408 IDirect3DVertexDeclaration9_Release(declaration2);
10409 IDirect3DStateBlock9_Release(stateblock);
10410 refcount = IDirect3DDevice9_Release(device);
10411 ok(!refcount, "Device has %u references left.\n", refcount);
10412 IDirect3D9_Release(d3d);
10413 DestroyWindow(window);
10416 static void test_resource_type(void)
10418 IDirect3DDevice9 *device;
10419 IDirect3DSurface9 *surface;
10420 IDirect3DTexture9 *texture;
10421 IDirect3DCubeTexture9 *cube_texture;
10422 IDirect3DVolume9 *volume;
10423 IDirect3DVolumeTexture9 *volume_texture;
10424 D3DSURFACE_DESC surface_desc;
10425 D3DVOLUME_DESC volume_desc;
10426 D3DRESOURCETYPE type;
10427 IDirect3D9 *d3d;
10428 ULONG refcount;
10429 HWND window;
10430 HRESULT hr;
10431 D3DCAPS9 caps;
10433 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10434 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10435 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10436 ok(!!d3d, "Failed to create a D3D object.\n");
10437 if (!(device = create_device(d3d, window, NULL)))
10439 skip("Failed to create a D3D device, skipping tests.\n");
10440 IDirect3D9_Release(d3d);
10441 DestroyWindow(window);
10442 return;
10445 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10446 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10448 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10449 D3DPOOL_SYSTEMMEM, &surface, NULL);
10450 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10451 type = IDirect3DSurface9_GetType(surface);
10452 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10453 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10454 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10455 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10456 surface_desc.Type);
10457 IDirect3DSurface9_Release(surface);
10459 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10460 D3DPOOL_SYSTEMMEM, &texture, NULL);
10461 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10462 type = IDirect3DTexture9_GetType(texture);
10463 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10465 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10466 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10467 /* The following code crashes, for the sake of completeness:
10468 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10469 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10471 * So applications will not depend on getting the "right" resource type - whatever it
10472 * may be - from the "wrong" vtable. */
10473 type = IDirect3DSurface9_GetType(surface);
10474 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10475 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10476 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10477 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10478 surface_desc.Type);
10479 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10480 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10481 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10482 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10483 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10484 surface_desc.Type);
10485 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10486 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10487 IDirect3DSurface9_Release(surface);
10489 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10490 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10491 type = IDirect3DSurface9_GetType(surface);
10492 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10493 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10494 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10495 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10496 surface_desc.Type);
10497 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10498 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10499 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10500 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10501 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10502 surface_desc.Type);
10503 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10504 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10505 IDirect3DSurface9_Release(surface);
10506 IDirect3DTexture9_Release(texture);
10508 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10510 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10511 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10512 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10513 type = IDirect3DCubeTexture9_GetType(cube_texture);
10514 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10516 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10517 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10518 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10519 type = IDirect3DSurface9_GetType(surface);
10520 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10521 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10522 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10523 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10524 surface_desc.Type);
10525 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10526 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10527 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10528 surface_desc.Type);
10529 IDirect3DSurface9_Release(surface);
10530 IDirect3DCubeTexture9_Release(cube_texture);
10532 else
10533 skip("Cube maps not supported.\n");
10535 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10537 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10538 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10539 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10540 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10541 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10543 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10544 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10545 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10546 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10547 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10548 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10549 volume_desc.Type);
10550 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10551 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10552 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10553 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
10554 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10555 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10556 volume_desc.Type);
10557 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10558 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10559 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10560 IDirect3DVolume9_Release(volume);
10562 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
10563 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10564 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10565 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10566 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10567 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10568 volume_desc.Type);
10569 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10570 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10571 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10572 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
10573 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10574 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10575 volume_desc.Type);
10576 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10577 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10578 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10579 IDirect3DVolume9_Release(volume);
10580 IDirect3DVolumeTexture9_Release(volume_texture);
10582 else
10583 skip("Mipmapped volume maps not supported.\n");
10585 refcount = IDirect3DDevice9_Release(device);
10586 ok(!refcount, "Device has %u references left.\n", refcount);
10587 IDirect3D9_Release(d3d);
10588 DestroyWindow(window);
10591 static void test_mipmap_lock(void)
10593 IDirect3DDevice9 *device;
10594 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
10595 IDirect3DTexture9 *texture, *texture_dst;
10596 IDirect3D9 *d3d;
10597 ULONG refcount;
10598 HWND window;
10599 HRESULT hr;
10600 D3DLOCKED_RECT locked_rect;
10602 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10603 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10604 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10605 ok(!!d3d, "Failed to create a D3D object.\n");
10606 if (!(device = create_device(d3d, window, NULL)))
10608 skip("Failed to create a D3D device, skipping tests.\n");
10609 IDirect3D9_Release(d3d);
10610 DestroyWindow(window);
10611 return;
10614 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10615 D3DPOOL_DEFAULT, &texture_dst, NULL);
10616 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10617 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
10618 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10619 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
10620 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10622 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10623 D3DPOOL_SYSTEMMEM, &texture, NULL);
10624 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10625 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10626 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10627 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
10628 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10630 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
10631 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10632 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
10633 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10634 hr = IDirect3DSurface9_UnlockRect(surface);
10635 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10637 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
10638 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
10639 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
10640 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10642 /* Apparently there's no validation on the container. */
10643 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
10644 (IDirect3DBaseTexture9 *)texture_dst);
10645 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
10647 hr = IDirect3DSurface9_UnlockRect(surface2);
10648 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10650 IDirect3DSurface9_Release(surface_dst2);
10651 IDirect3DSurface9_Release(surface_dst);
10652 IDirect3DSurface9_Release(surface2);
10653 IDirect3DSurface9_Release(surface);
10654 IDirect3DTexture9_Release(texture_dst);
10655 IDirect3DTexture9_Release(texture);
10657 refcount = IDirect3DDevice9_Release(device);
10658 ok(!refcount, "Device has %u references left.\n", refcount);
10659 IDirect3D9_Release(d3d);
10660 DestroyWindow(window);
10663 static void test_writeonly_resource(void)
10665 IDirect3D9 *d3d;
10666 IDirect3DDevice9 *device;
10667 IDirect3DVertexBuffer9 *buffer;
10668 ULONG refcount;
10669 HWND window;
10670 HRESULT hr;
10671 void *ptr;
10672 static const struct
10674 struct vec3 pos;
10676 quad[] =
10678 {{-1.0f, -1.0f, 0.0f}},
10679 {{-1.0f, 1.0f, 0.0f}},
10680 {{ 1.0f, -1.0f, 0.0f}},
10681 {{ 1.0f, 1.0f, 0.0f}}
10684 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10685 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10686 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10687 ok(!!d3d, "Failed to create a D3D object.\n");
10688 if (!(device = create_device(d3d, window, NULL)))
10690 skip("Failed to create a D3D device, skipping tests.\n");
10691 IDirect3D9_Release(d3d);
10692 DestroyWindow(window);
10693 return;
10696 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
10697 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
10698 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
10700 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10701 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10702 memcpy(ptr, quad, sizeof(quad));
10703 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10704 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10705 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
10706 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
10707 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10708 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10710 hr = IDirect3DDevice9_BeginScene(device);
10711 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
10712 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
10713 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10714 hr = IDirect3DDevice9_EndScene(device);
10715 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
10717 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
10718 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10719 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10720 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10721 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10723 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
10724 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10725 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10726 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10727 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10729 refcount = IDirect3DVertexBuffer9_Release(buffer);
10730 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
10731 refcount = IDirect3DDevice9_Release(device);
10732 ok(!refcount, "Device has %u references left.\n", refcount);
10733 IDirect3D9_Release(d3d);
10734 DestroyWindow(window);
10737 static void test_lost_device(void)
10739 struct device_desc device_desc;
10740 IDirect3DDevice9 *device;
10741 IDirect3D9 *d3d;
10742 ULONG refcount;
10743 HWND window;
10744 HRESULT hr;
10745 BOOL ret;
10747 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10748 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10749 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10750 ok(!!d3d, "Failed to create a D3D object.\n");
10751 device_desc.device_window = window;
10752 device_desc.width = registry_mode.dmPelsWidth;
10753 device_desc.height = registry_mode.dmPelsHeight;
10754 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10755 if (!(device = create_device(d3d, window, &device_desc)))
10757 skip("Failed to create a D3D device, skipping tests.\n");
10758 goto done;
10761 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10762 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10763 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10764 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10766 ret = SetForegroundWindow(GetDesktopWindow());
10767 ok(ret, "Failed to set foreground window.\n");
10768 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10769 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10770 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10771 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10773 ret = ShowWindow(window, SW_RESTORE);
10774 ok(ret, "Failed to restore window.\n");
10775 ret = SetForegroundWindow(window);
10776 ok(ret, "Failed to set foreground window.\n");
10777 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10778 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
10779 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10780 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10782 hr = reset_device(device, &device_desc);
10783 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10784 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10785 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10786 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10787 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10789 device_desc.flags = 0;
10790 hr = reset_device(device, &device_desc);
10791 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10792 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10793 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10794 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10795 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10797 ret = SetForegroundWindow(GetDesktopWindow());
10798 ok(ret, "Failed to set foreground window.\n");
10799 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10800 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10801 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10802 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10804 ret = ShowWindow(window, SW_RESTORE);
10805 ok(ret, "Failed to restore window.\n");
10806 ret = SetForegroundWindow(window);
10807 ok(ret, "Failed to set foreground window.\n");
10808 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10809 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10810 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10811 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10813 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10814 hr = reset_device(device, &device_desc);
10815 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10816 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10817 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10818 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10819 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10821 ret = SetForegroundWindow(GetDesktopWindow());
10822 ok(ret, "Failed to set foreground window.\n");
10823 hr = reset_device(device, &device_desc);
10824 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10825 ret = ShowWindow(window, SW_RESTORE);
10826 ok(ret, "Failed to restore window.\n");
10827 ret = SetForegroundWindow(window);
10828 ok(ret, "Failed to set foreground window.\n");
10829 hr = reset_device(device, &device_desc);
10830 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10832 refcount = IDirect3DDevice9_Release(device);
10833 ok(!refcount, "Device has %u references left.\n", refcount);
10834 done:
10835 IDirect3D9_Release(d3d);
10836 DestroyWindow(window);
10839 static void test_resource_priority(void)
10841 IDirect3DDevice9 *device;
10842 IDirect3DSurface9 *surface;
10843 IDirect3DTexture9 *texture;
10844 IDirect3DVertexBuffer9 *buffer;
10845 IDirect3D9 *d3d;
10846 ULONG refcount;
10847 HWND window;
10848 HRESULT hr;
10849 static const struct
10851 D3DPOOL pool;
10852 const char *name;
10853 BOOL can_set_priority;
10855 test_data[] =
10857 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
10858 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
10859 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
10860 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
10862 unsigned int i;
10863 DWORD priority;
10865 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10866 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10867 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10868 ok(!!d3d, "Failed to create a D3D object.\n");
10869 if (!(device = create_device(d3d, window, NULL)))
10871 skip("Failed to create a D3D device, skipping tests.\n");
10872 IDirect3D9_Release(d3d);
10873 DestroyWindow(window);
10874 return;
10877 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
10879 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
10880 test_data[i].pool, &texture, NULL);
10881 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
10882 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10883 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10885 priority = IDirect3DTexture9_GetPriority(texture);
10886 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10887 priority = IDirect3DTexture9_SetPriority(texture, 1);
10888 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10889 priority = IDirect3DTexture9_GetPriority(texture);
10890 if (test_data[i].can_set_priority)
10892 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10893 priority = IDirect3DTexture9_SetPriority(texture, 2);
10894 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10896 else
10897 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10899 priority = IDirect3DSurface9_GetPriority(surface);
10900 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10901 priority = IDirect3DSurface9_SetPriority(surface, 1);
10902 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10903 priority = IDirect3DSurface9_GetPriority(surface);
10904 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10906 IDirect3DSurface9_Release(surface);
10907 IDirect3DTexture9_Release(texture);
10909 if (test_data[i].pool != D3DPOOL_MANAGED)
10911 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
10912 test_data[i].pool, &surface, NULL);
10913 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
10915 priority = IDirect3DSurface9_GetPriority(surface);
10916 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10917 priority = IDirect3DSurface9_SetPriority(surface, 1);
10918 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10919 priority = IDirect3DSurface9_GetPriority(surface);
10920 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10922 IDirect3DSurface9_Release(surface);
10925 if (test_data[i].pool != D3DPOOL_SCRATCH)
10927 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
10928 test_data[i].pool, &buffer, NULL);
10929 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
10931 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10932 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10933 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
10934 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10935 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10936 if (test_data[i].can_set_priority)
10938 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10939 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
10940 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10942 else
10943 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10945 IDirect3DVertexBuffer9_Release(buffer);
10949 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
10950 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
10952 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
10953 priority = IDirect3DSurface9_GetPriority(surface);
10954 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10955 priority = IDirect3DSurface9_SetPriority(surface, 1);
10956 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10957 priority = IDirect3DSurface9_GetPriority(surface);
10958 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10960 IDirect3DSurface9_Release(surface);
10962 refcount = IDirect3DDevice9_Release(device);
10963 ok(!refcount, "Device has %u references left.\n", refcount);
10964 IDirect3D9_Release(d3d);
10965 DestroyWindow(window);
10968 static void test_swapchain_parameters(void)
10970 IDirect3DDevice9 *device;
10971 IDirect3D9 *d3d;
10972 HWND window;
10973 HRESULT hr;
10974 unsigned int i;
10975 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
10976 IDirect3DSwapChain9 *swapchain;
10977 static const struct
10979 BOOL windowed;
10980 UINT backbuffer_count;
10981 D3DSWAPEFFECT swap_effect;
10982 HRESULT hr;
10984 tests[] =
10986 /* Swap effect 0 is not allowed. */
10987 {TRUE, 1, 0, D3DERR_INVALIDCALL},
10988 {FALSE, 1, 0, D3DERR_INVALIDCALL},
10990 /* All (non-ex) swap effects are allowed in
10991 * windowed and fullscreen mode. */
10992 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10993 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10994 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10995 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10996 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10998 /* Only one backbuffer in copy mode. */
10999 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
11000 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11001 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11002 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11004 /* Ok with the others, in fullscreen and windowed mode. */
11005 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11006 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11007 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11008 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11010 /* D3D9Ex swap effects. */
11011 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11012 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11013 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11014 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11015 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11016 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11018 /* 3 is the highest allowed backbuffer count. */
11019 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11020 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11021 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11022 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11023 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11026 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11027 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11028 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11029 ok(!!d3d, "Failed to create a D3D object.\n");
11030 if (!(device = create_device(d3d, window, NULL)))
11032 skip("Failed to create a D3D device, skipping tests.\n");
11033 IDirect3D9_Release(d3d);
11034 DestroyWindow(window);
11035 return;
11037 IDirect3DDevice9_Release(device);
11039 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11040 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11041 present_parameters_windowed.hDeviceWindow = window;
11042 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11043 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11044 present_parameters_windowed.Windowed = TRUE;
11045 present_parameters_windowed.BackBufferCount = 1;
11047 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
11049 memset(&present_parameters, 0, sizeof(present_parameters));
11050 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11051 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11052 present_parameters.hDeviceWindow = window;
11053 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11055 present_parameters.SwapEffect = tests[i].swap_effect;
11056 present_parameters.Windowed = tests[i].windowed;
11057 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11059 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11060 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11061 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11062 if (SUCCEEDED(hr))
11064 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11066 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11067 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11069 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11070 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11071 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11072 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11073 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11074 bb_count, present_parameters2.BackBufferCount, i);
11075 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11076 tests[i].windowed, present_parameters2.Windowed, i);
11078 IDirect3DSwapChain9_Release(swapchain);
11079 IDirect3DDevice9_Release(device);
11082 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11083 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11084 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11086 memset(&present_parameters, 0, sizeof(present_parameters));
11087 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11088 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11089 present_parameters.hDeviceWindow = window;
11090 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11092 present_parameters.SwapEffect = tests[i].swap_effect;
11093 present_parameters.Windowed = tests[i].windowed;
11094 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11096 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11097 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11099 if (FAILED(hr))
11101 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11102 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11104 IDirect3DDevice9_Release(device);
11107 IDirect3D9_Release(d3d);
11108 DestroyWindow(window);
11111 static void test_check_device_format(void)
11113 IDirect3D9 *d3d;
11114 HRESULT hr;
11116 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11117 ok(!!d3d, "Failed to create a D3D object.\n");
11119 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11120 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11122 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11124 else
11126 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11127 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11128 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11129 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11130 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11131 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11134 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11135 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11136 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11137 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11138 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11139 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11140 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11141 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11142 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11144 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11145 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11146 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11147 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11148 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11149 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11150 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11151 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11152 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11154 IDirect3D9_Release(d3d);
11157 static void test_miptree_layout(void)
11159 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11160 IDirect3DCubeTexture9 *texture_cube;
11161 IDirect3DTexture9 *texture_2d;
11162 IDirect3DDevice9 *device;
11163 D3DLOCKED_RECT map_desc;
11164 BYTE *base = NULL;
11165 IDirect3D9 *d3d;
11166 D3DCAPS9 caps;
11167 UINT refcount;
11168 HWND window;
11169 HRESULT hr;
11171 static const struct
11173 D3DFORMAT format;
11174 const char *name;
11176 formats[] =
11178 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11179 {D3DFMT_A8, "D3DFMT_A8"},
11180 {D3DFMT_L8, "D3DFMT_L8"},
11181 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11182 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11184 static const struct
11186 D3DPOOL pool;
11187 const char *name;
11189 pools[] =
11191 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11192 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11193 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11196 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11197 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11198 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11199 ok(!!d3d, "Failed to create a D3D object.\n");
11200 if (!(device = create_device(d3d, window, NULL)))
11202 skip("Failed to create a D3D device, skipping tests.\n");
11203 goto done;
11206 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11207 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11209 base_dimension = 257;
11210 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11212 skip("Using power of two base dimension.\n");
11213 base_dimension = 256;
11216 for (format_idx = 0; format_idx < sizeof(formats) / sizeof(*formats); ++format_idx)
11218 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11219 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11221 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11222 continue;
11225 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11227 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11228 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11229 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11230 pools[pool_idx].name, formats[format_idx].name, hr);
11232 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11233 for (i = 0, offset = 0; i < level_count; ++i)
11235 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11236 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11237 pools[pool_idx].name, formats[format_idx].name, i, hr);
11239 if (!i)
11240 base = map_desc.pBits;
11241 else
11242 ok(map_desc.pBits == base + offset,
11243 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11244 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11245 offset += (base_dimension >> i) * map_desc.Pitch;
11247 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11248 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11249 pools[pool_idx].name, formats[format_idx].name, i, hr);
11252 IDirect3DTexture9_Release(texture_2d);
11255 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11256 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11258 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11259 continue;
11262 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11264 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11265 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11266 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11267 pools[pool_idx].name, formats[format_idx].name, hr);
11269 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11270 for (i = 0, offset = 0; i < 6; ++i)
11272 for (j = 0; j < level_count; ++j)
11274 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11275 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11276 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11278 if (!i && !j)
11279 base = map_desc.pBits;
11280 else
11281 ok(map_desc.pBits == base + offset,
11282 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11283 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11284 offset += (base_dimension >> j) * map_desc.Pitch;
11286 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11287 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11288 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11290 offset = (offset + 15) & ~15;
11293 IDirect3DCubeTexture9_Release(texture_cube);
11297 refcount = IDirect3DDevice9_Release(device);
11298 ok(!refcount, "Device has %u references left.\n", refcount);
11299 done:
11300 IDirect3D9_Release(d3d);
11301 DestroyWindow(window);
11304 static void test_get_render_target_data(void)
11306 IDirect3DSurface9 *offscreen_surface, *render_target;
11307 IDirect3DDevice9 *device;
11308 IDirect3D9 *d3d;
11309 UINT refcount;
11310 HWND window;
11311 HRESULT hr;
11313 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11314 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11315 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11316 ok(!!d3d, "Failed to create a D3D object.\n");
11317 if (!(device = create_device(d3d, window, NULL)))
11319 skip("Failed to create a D3D device.\n");
11320 IDirect3D9_Release(d3d);
11321 DestroyWindow(window);
11322 return;
11325 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11326 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11327 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11329 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11330 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11331 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11333 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11334 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11336 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11337 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11339 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11340 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11342 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11343 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11345 IDirect3DSurface9_Release(render_target);
11346 IDirect3DSurface9_Release(offscreen_surface);
11347 refcount = IDirect3DDevice9_Release(device);
11348 ok(!refcount, "Device has %u references left.\n", refcount);
11349 IDirect3D9_Release(d3d);
11350 DestroyWindow(window);
11353 static void test_render_target_device_mismatch(void)
11355 IDirect3DDevice9 *device, *device2;
11356 IDirect3DSurface9 *surface, *rt;
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_GetRenderTarget(device, 0, &rt);
11375 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11377 device2 = create_device(d3d, window, NULL);
11378 ok(!!device2, "Failed to create a D3D device.\n");
11380 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11381 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11382 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11384 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11385 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11387 IDirect3DSurface9_Release(surface);
11389 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11390 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11392 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11393 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11395 IDirect3DSurface9_Release(surface);
11397 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11398 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11399 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11400 IDirect3DSurface9_Release(surface);
11401 IDirect3DSurface9_Release(rt);
11403 refcount = IDirect3DDevice9_Release(device);
11404 ok(!refcount, "Device has %u references left.\n", refcount);
11405 refcount = IDirect3DDevice9_Release(device2);
11406 ok(!refcount, "Device has %u references left.\n", refcount);
11407 IDirect3D9_Release(d3d);
11408 DestroyWindow(window);
11411 START_TEST(device)
11413 WNDCLASSA wc = {0};
11414 IDirect3D9 *d3d9;
11415 DEVMODEW current_mode;
11417 memset(&current_mode, 0, sizeof(current_mode));
11418 current_mode.dmSize = sizeof(current_mode);
11419 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
11420 registry_mode.dmSize = sizeof(registry_mode);
11421 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
11422 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
11423 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
11425 skip("Current mode does not match registry mode, skipping test.\n");
11426 return;
11429 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
11431 skip("could not create D3D9 object\n");
11432 return;
11434 IDirect3D9_Release(d3d9);
11436 wc.lpfnWndProc = DefWindowProcA;
11437 wc.lpszClassName = "d3d9_test_wc";
11438 RegisterClassA(&wc);
11440 test_get_set_vertex_declaration();
11441 test_get_declaration();
11442 test_fvf_decl_conversion();
11443 test_fvf_decl_management();
11444 test_vertex_declaration_alignment();
11445 test_unused_declaration_type();
11446 test_fpu_setup();
11447 test_multi_device();
11448 test_display_formats();
11449 test_display_modes();
11450 test_swapchain();
11451 test_refcount();
11452 test_mipmap_levels();
11453 test_checkdevicemultisampletype();
11454 test_invalid_multisample();
11455 test_cursor();
11456 test_cursor_pos();
11457 test_reset_fullscreen();
11458 test_reset();
11459 test_scene();
11460 test_limits();
11461 test_depthstenciltest();
11462 test_get_rt();
11463 test_draw_primitive();
11464 test_null_stream();
11465 test_lights();
11466 test_set_stream_source();
11467 test_scissor_size();
11468 test_wndproc();
11469 test_wndproc_windowed();
11470 test_window_style();
11471 test_mode_change();
11472 test_device_window_reset();
11473 test_reset_resources();
11474 test_set_rt_vp_scissor();
11475 test_volume_get_container();
11476 test_volume_resource();
11477 test_vb_lock_flags();
11478 test_vertex_buffer_alignment();
11479 test_query_support();
11480 test_occlusion_query();
11481 test_timestamp_query();
11482 test_get_set_vertex_shader();
11483 test_vertex_shader_constant();
11484 test_get_set_pixel_shader();
11485 test_pixel_shader_constant();
11486 test_unsupported_shaders();
11487 test_texture_stage_states();
11488 test_cube_textures();
11489 test_mipmap_gen();
11490 test_filter();
11491 test_get_set_texture();
11492 test_lod();
11493 test_surface_get_container();
11494 test_surface_alignment();
11495 test_lockrect_offset();
11496 test_lockrect_invalid();
11497 test_private_data();
11498 test_getdc();
11499 test_surface_dimensions();
11500 test_surface_format_null();
11501 test_surface_double_unlock();
11502 test_surface_blocks();
11503 test_set_palette();
11504 test_swvp_buffer();
11505 test_managed_buffer();
11506 test_npot_textures();
11507 test_vidmem_accounting();
11508 test_volume_locking();
11509 test_update_volumetexture();
11510 test_create_rt_ds_fail();
11511 test_volume_blocks();
11512 test_lockbox_invalid();
11513 test_shared_handle();
11514 test_pixel_format();
11515 test_begin_end_state_block();
11516 test_shader_constant_apply();
11517 test_vdecl_apply();
11518 test_resource_type();
11519 test_mipmap_lock();
11520 test_writeonly_resource();
11521 test_lost_device();
11522 test_resource_priority();
11523 test_swapchain_parameters();
11524 test_check_device_format();
11525 test_miptree_layout();
11526 test_get_render_target_data();
11527 test_render_target_device_mismatch();
11529 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));