d3d9: Reject render target surfaces created for other devices.
[wine.git] / dlls / d3d9 / tests / device.c
blobaa266a5186e85272db8a17bfcfa6daf23853d018
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 IDirect3D9 *d3d;
7300 unsigned int i, r;
7301 ULONG refcount;
7302 HWND window;
7303 BYTE *base;
7304 HRESULT hr;
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);
7378 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7380 unsigned int offset, expected_offset;
7381 const RECT *rect = &test_data[i].rect;
7383 locked_rect.pBits = (BYTE *)0xdeadbeef;
7384 locked_rect.Pitch = 0xdeadbeef;
7386 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7387 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7388 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7389 * one broken. */
7390 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7391 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7392 wine_dbgstr_rect(rect), hr, resources[r].name);
7393 if (FAILED(hr))
7394 continue;
7396 offset = (BYTE *)locked_rect.pBits - base;
7397 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7398 ok(offset == expected_offset,
7399 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7400 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7402 hr = IDirect3DSurface9_UnlockRect(surface);
7403 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7405 if (texture)
7407 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7408 ok(SUCCEEDED(hr),
7409 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7410 wine_dbgstr_rect(rect), hr, resources[r].name);
7411 if (FAILED(hr))
7412 continue;
7414 offset = (BYTE *)locked_rect.pBits - base;
7415 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7416 ok(offset == expected_offset,
7417 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7418 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7420 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7421 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7423 if (cube_texture)
7425 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7426 &locked_rect, rect, 0);
7427 ok(SUCCEEDED(hr),
7428 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7429 wine_dbgstr_rect(rect), hr, resources[r].name);
7430 if (FAILED(hr))
7431 continue;
7433 offset = (BYTE *)locked_rect.pBits - base;
7434 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7435 ok(offset == expected_offset,
7436 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7437 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7439 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7440 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7444 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7445 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7446 locked_rect.pBits = (BYTE *)0xdeadbeef;
7447 locked_rect.Pitch = 1;
7448 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7449 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7450 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7451 locked_rect.pBits, resources[r].name);
7452 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7453 locked_rect.Pitch, resources[r].name);
7454 hr = IDirect3DSurface9_UnlockRect(surface);
7455 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7457 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7458 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7459 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7460 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7461 ok(hr == D3DERR_INVALIDCALL, "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_rect_2, 0);
7464 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7465 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7466 hr = IDirect3DSurface9_UnlockRect(surface);
7467 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7469 IDirect3DSurface9_Release(surface);
7471 if (texture)
7473 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7474 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7475 hr, resources[r].name);
7476 locked_rect.pBits = (BYTE *)0xdeadbeef;
7477 locked_rect.Pitch = 1;
7478 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7479 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7480 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7481 locked_rect.pBits, resources[r].name);
7482 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7483 locked_rect.Pitch, resources[r].name);
7484 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7485 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7486 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7487 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7489 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7490 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7491 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7492 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7493 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7494 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7495 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7496 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7497 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7498 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7499 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7501 IDirect3DTexture9_Release(texture);
7503 if (cube_texture)
7505 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7506 &locked_rect, NULL, 0);
7507 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7508 hr, resources[r].name);
7509 locked_rect.pBits = (BYTE *)0xdeadbeef;
7510 locked_rect.Pitch = 1;
7511 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7512 &locked_rect, NULL, 0);
7513 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7514 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7515 locked_rect.pBits, resources[r].name);
7516 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7517 locked_rect.Pitch, resources[r].name);
7518 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7519 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7520 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7521 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7523 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7524 &locked_rect, &test_data[0].rect, 0);
7525 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7526 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7527 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7528 &locked_rect, &test_data[0].rect, 0);
7529 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7530 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7531 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7532 &locked_rect, &test_rect_2, 0);
7533 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7534 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7535 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7536 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7538 IDirect3DCubeTexture9_Release(cube_texture);
7542 refcount = IDirect3DDevice9_Release(device);
7543 ok(!refcount, "Device has %u references left.\n", refcount);
7544 IDirect3D9_Release(d3d);
7545 DestroyWindow(window);
7548 static void test_private_data(void)
7550 ULONG refcount, expected_refcount;
7551 IDirect3DTexture9 *texture;
7552 IDirect3DSurface9 *surface, *surface2;
7553 IDirect3DDevice9 *device;
7554 IDirect3D9 *d3d;
7555 IUnknown *ptr;
7556 HWND window;
7557 HRESULT hr;
7558 DWORD size;
7559 DWORD data[4] = {1, 2, 3, 4};
7560 static const GUID d3d9_private_data_test_guid2 =
7562 0x2e5afac2,
7563 0x87b5,
7564 0x4c10,
7565 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7568 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7569 0, 0, 640, 480, 0, 0, 0, 0);
7570 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7571 ok(!!d3d, "Failed to create a D3D object.\n");
7572 if (!(device = create_device(d3d, window, NULL)))
7574 skip("Failed to create a D3D device, skipping tests.\n");
7575 IDirect3D9_Release(d3d);
7576 DestroyWindow(window);
7577 return;
7580 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7581 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7582 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7584 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7585 device, 0, D3DSPD_IUNKNOWN);
7586 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7587 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7588 device, 5, D3DSPD_IUNKNOWN);
7589 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7590 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7591 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7592 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7594 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7595 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7596 sizeof(device), D3DSPD_IUNKNOWN);
7597 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7598 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7599 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7600 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7601 size = sizeof(ptr);
7602 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7603 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7604 IUnknown_Release(ptr);
7605 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7606 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7608 refcount = get_refcount((IUnknown *)device);
7609 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7610 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7611 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7612 expected_refcount = refcount + 1;
7613 refcount = get_refcount((IUnknown *)device);
7614 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7615 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7616 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7617 expected_refcount = refcount - 1;
7618 refcount = get_refcount((IUnknown *)device);
7619 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7621 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7622 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7623 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7624 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7625 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7626 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7627 refcount = get_refcount((IUnknown *)device);
7628 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7630 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7631 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7632 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7633 size = 2 * sizeof(ptr);
7634 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7635 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7636 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7637 expected_refcount = refcount + 2;
7638 refcount = get_refcount((IUnknown *)device);
7639 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7640 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
7641 IUnknown_Release(ptr);
7642 expected_refcount--;
7644 ptr = (IUnknown *)0xdeadbeef;
7645 size = 1;
7646 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7647 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7648 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7649 size = 2 * sizeof(ptr);
7650 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7651 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7652 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7653 refcount = get_refcount((IUnknown *)device);
7654 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7655 size = 1;
7656 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7657 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7658 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7659 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7660 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
7661 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7662 size = 0xdeadbabe;
7663 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
7664 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7665 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7666 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7667 /* GetPrivateData with size = NULL causes an access violation on Windows if the
7668 * requested data exists. */
7670 /* Destroying the surface frees the held reference. */
7671 IDirect3DSurface9_Release(surface);
7672 expected_refcount = refcount - 2;
7673 refcount = get_refcount((IUnknown *)device);
7674 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7676 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
7677 &texture, NULL);
7678 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7679 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7680 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
7681 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
7682 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
7684 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7685 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7687 memset(data, 0, sizeof(data));
7688 size = sizeof(data);
7689 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
7690 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7691 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
7692 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7693 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
7694 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
7696 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
7697 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7699 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7700 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7701 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
7702 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7704 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7705 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7707 IDirect3DSurface9_Release(surface2);
7708 IDirect3DSurface9_Release(surface);
7709 IDirect3DTexture9_Release(texture);
7711 refcount = IDirect3DDevice9_Release(device);
7712 ok(!refcount, "Device has %u references left.\n", refcount);
7713 IDirect3D9_Release(d3d);
7714 DestroyWindow(window);
7717 static void test_getdc(void)
7719 static const struct
7721 const char *name;
7722 D3DFORMAT format;
7723 unsigned int bit_count;
7724 DWORD mask_r, mask_g, mask_b;
7725 BOOL getdc_supported;
7727 testdata[] =
7729 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7730 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7731 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
7732 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7733 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7734 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
7735 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7736 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7737 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7738 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7739 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7740 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7741 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7742 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7743 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7744 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
7745 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7746 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7747 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7748 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7750 IDirect3DSurface9 *surface, *surface2;
7751 IDirect3DCubeTexture9 *cube_texture;
7752 IDirect3DTexture9 *texture;
7753 IDirect3DDevice9 *device;
7754 D3DLOCKED_RECT map_desc;
7755 IDirect3D9 *d3d;
7756 unsigned int i;
7757 ULONG refcount;
7758 HWND window;
7759 HDC dc, dc2;
7760 HRESULT hr;
7762 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7763 0, 0, 640, 480, 0, 0, 0, 0);
7764 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7765 ok(!!d3d, "Failed to create a D3D object.\n");
7766 if (!(device = create_device(d3d, window, NULL)))
7768 skip("Failed to create a D3D device, skipping tests.\n");
7769 IDirect3D9_Release(d3d);
7770 DestroyWindow(window);
7771 return;
7774 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
7776 texture = NULL;
7777 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7778 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
7779 if (FAILED(hr))
7781 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
7782 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
7783 if (FAILED(hr))
7785 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7786 continue;
7788 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7789 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7792 dc = (void *)0x1234;
7793 hr = IDirect3DSurface9_GetDC(surface, &dc);
7794 if (testdata[i].getdc_supported)
7795 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7796 else
7797 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7799 if (SUCCEEDED(hr))
7801 unsigned int width_bytes;
7802 DIBSECTION dib;
7803 HBITMAP bitmap;
7804 DWORD type;
7805 int size;
7807 type = GetObjectType(dc);
7808 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7809 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7810 type = GetObjectType(bitmap);
7811 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
7813 size = GetObjectA(bitmap, sizeof(dib), &dib);
7814 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
7815 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
7816 dib.dsBm.bmType, testdata[i].name);
7817 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
7818 dib.dsBm.bmWidth, testdata[i].name);
7819 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
7820 dib.dsBm.bmHeight, testdata[i].name);
7821 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
7822 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
7823 dib.dsBm.bmWidthBytes, testdata[i].name);
7824 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
7825 dib.dsBm.bmPlanes, testdata[i].name);
7826 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
7827 "Got unexpected bit count %d for format %s.\n",
7828 dib.dsBm.bmBitsPixel, testdata[i].name);
7829 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
7830 dib.dsBm.bmBits, testdata[i].name);
7832 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
7833 dib.dsBmih.biSize, testdata[i].name);
7834 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
7835 dib.dsBmih.biHeight, testdata[i].name);
7836 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
7837 dib.dsBmih.biHeight, testdata[i].name);
7838 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
7839 dib.dsBmih.biPlanes, testdata[i].name);
7840 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
7841 dib.dsBmih.biBitCount, testdata[i].name);
7842 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
7843 "Got unexpected compression %#x for format %s.\n",
7844 dib.dsBmih.biCompression, testdata[i].name);
7845 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
7846 dib.dsBmih.biSizeImage, testdata[i].name);
7847 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
7848 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
7849 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
7850 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
7851 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
7852 dib.dsBmih.biClrUsed, testdata[i].name);
7853 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
7854 dib.dsBmih.biClrImportant, testdata[i].name);
7856 if (dib.dsBmih.biCompression == BI_BITFIELDS)
7858 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
7859 && dib.dsBitfields[2] == testdata[i].mask_b,
7860 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7861 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7863 else
7865 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
7866 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
7867 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
7869 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
7870 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
7872 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7873 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
7875 else
7877 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
7880 IDirect3DSurface9_Release(surface);
7881 if (texture)
7882 IDirect3DTexture9_Release(texture);
7884 if (!testdata[i].getdc_supported)
7885 continue;
7887 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
7888 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
7890 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7891 continue;
7894 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
7895 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7896 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
7897 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
7899 hr = IDirect3DSurface9_GetDC(surface, &dc);
7900 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7901 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7902 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7903 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7904 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7905 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7906 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7908 hr = IDirect3DSurface9_GetDC(surface, &dc);
7909 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7910 dc2 = (void *)0x1234;
7911 hr = IDirect3DSurface9_GetDC(surface, &dc2);
7912 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7913 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
7914 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7915 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7916 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7917 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7919 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7920 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7921 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7922 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7923 hr = IDirect3DSurface9_UnlockRect(surface);
7924 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7925 hr = IDirect3DSurface9_UnlockRect(surface);
7926 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7928 hr = IDirect3DSurface9_GetDC(surface, &dc);
7929 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7930 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7931 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7932 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7933 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7935 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7936 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7937 hr = IDirect3DSurface9_GetDC(surface, &dc);
7938 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7939 hr = IDirect3DSurface9_UnlockRect(surface);
7940 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7942 hr = IDirect3DSurface9_GetDC(surface, &dc);
7943 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7944 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
7945 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7946 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
7947 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7948 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7949 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7951 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7952 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7953 hr = IDirect3DSurface9_GetDC(surface, &dc2);
7954 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7955 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
7956 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7957 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
7958 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7960 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7961 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7962 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7963 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7964 hr = IDirect3DSurface9_UnlockRect(surface2);
7965 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7966 hr = IDirect3DSurface9_UnlockRect(surface);
7967 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7969 hr = IDirect3DSurface9_LockRect(surface, &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_GetDC(surface, &dc);
7972 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7973 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7974 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7975 hr = IDirect3DSurface9_UnlockRect(surface);
7976 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7978 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
7979 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
7980 hr = IDirect3DSurface9_GetDC(surface, &dc);
7981 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7982 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7983 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7984 hr = IDirect3DSurface9_UnlockRect(surface2);
7985 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
7987 hr = IDirect3DSurface9_GetDC(surface, &dc);
7988 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7989 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
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);
7993 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7994 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
7996 hr = IDirect3DSurface9_GetDC(surface2, &dc);
7997 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
7998 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
7999 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8000 hr = IDirect3DSurface9_UnlockRect(surface);
8001 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8002 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8003 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8005 hr = IDirect3DSurface9_UnlockRect(surface);
8006 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8007 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8008 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8009 hr = IDirect3DSurface9_UnlockRect(surface);
8010 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8011 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8012 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8013 hr = IDirect3DSurface9_UnlockRect(surface);
8014 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8016 hr = IDirect3DSurface9_UnlockRect(surface2);
8017 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8018 hr = IDirect3DSurface9_GetDC(surface, &dc);
8019 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8020 hr = IDirect3DSurface9_UnlockRect(surface2);
8021 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8022 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8023 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8024 hr = IDirect3DSurface9_UnlockRect(surface2);
8025 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8027 IDirect3DSurface9_Release(surface2);
8028 IDirect3DSurface9_Release(surface);
8029 IDirect3DCubeTexture9_Release(cube_texture);
8032 refcount = IDirect3DDevice9_Release(device);
8033 ok(!refcount, "Device has %u references left.\n", refcount);
8034 IDirect3D9_Release(d3d);
8035 DestroyWindow(window);
8038 static void test_surface_dimensions(void)
8040 IDirect3DSurface9 *surface;
8041 IDirect3DDevice9 *device;
8042 IDirect3D9 *d3d;
8043 ULONG refcount;
8044 HWND window;
8045 HRESULT hr;
8047 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8048 0, 0, 640, 480, 0, 0, 0, 0);
8049 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8050 ok(!!d3d, "Failed to create a D3D object.\n");
8051 if (!(device = create_device(d3d, window, NULL)))
8053 skip("Failed to create a D3D device, skipping tests.\n");
8054 IDirect3D9_Release(d3d);
8055 DestroyWindow(window);
8056 return;
8059 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8060 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8061 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8062 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8063 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8064 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8066 refcount = IDirect3DDevice9_Release(device);
8067 ok(!refcount, "Device has %u references left.\n", refcount);
8068 IDirect3D9_Release(d3d);
8069 DestroyWindow(window);
8072 static void test_surface_format_null(void)
8074 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8075 IDirect3DTexture9 *texture;
8076 IDirect3DSurface9 *surface;
8077 IDirect3DSurface9 *rt, *ds;
8078 D3DLOCKED_RECT locked_rect;
8079 IDirect3DDevice9 *device;
8080 D3DSURFACE_DESC desc;
8081 IDirect3D9 *d3d;
8082 ULONG refcount;
8083 HWND window;
8084 HRESULT hr;
8086 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8087 ok(!!d3d, "Failed to create a D3D object.\n");
8089 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8090 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8091 if (hr != D3D_OK)
8093 skip("No D3DFMT_NULL support, skipping test.\n");
8094 IDirect3D9_Release(d3d);
8095 return;
8098 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8099 0, 0, 640, 480, 0, 0, 0, 0);
8100 if (!(device = create_device(d3d, window, NULL)))
8102 skip("Failed to create a D3D device, skipping tests.\n");
8103 IDirect3D9_Release(d3d);
8104 DestroyWindow(window);
8105 return;
8108 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8109 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8110 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8112 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8113 D3DFMT_NULL, D3DFMT_D24S8);
8114 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8116 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8117 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8118 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8120 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8121 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8123 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8124 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8126 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8127 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8129 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8130 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8132 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8133 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8135 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8136 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8138 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8139 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8141 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8142 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8144 IDirect3DSurface9_Release(rt);
8145 IDirect3DSurface9_Release(ds);
8147 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8148 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8149 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8150 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8152 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8153 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8154 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8155 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8157 hr = IDirect3DSurface9_UnlockRect(surface);
8158 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8160 IDirect3DSurface9_Release(surface);
8162 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8163 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8164 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8165 IDirect3DTexture9_Release(texture);
8167 refcount = IDirect3DDevice9_Release(device);
8168 ok(!refcount, "Device has %u references left.\n", refcount);
8169 IDirect3D9_Release(d3d);
8170 DestroyWindow(window);
8173 static void test_surface_double_unlock(void)
8175 static const D3DPOOL pools[] =
8177 D3DPOOL_DEFAULT,
8178 D3DPOOL_SCRATCH,
8179 D3DPOOL_SYSTEMMEM,
8181 IDirect3DSurface9 *surface;
8182 IDirect3DDevice9 *device;
8183 D3DLOCKED_RECT lr;
8184 IDirect3D9 *d3d;
8185 unsigned int i;
8186 ULONG refcount;
8187 HWND window;
8188 HRESULT hr;
8190 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8191 0, 0, 640, 480, 0, 0, 0, 0);
8192 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8193 ok(!!d3d, "Failed to create a D3D object.\n");
8194 if (!(device = create_device(d3d, window, NULL)))
8196 skip("Failed to create a D3D device, skipping tests.\n");
8197 IDirect3D9_Release(d3d);
8198 DestroyWindow(window);
8199 return;
8202 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
8204 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8205 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8206 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8208 hr = IDirect3DSurface9_UnlockRect(surface);
8209 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8210 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8211 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8212 hr = IDirect3DSurface9_UnlockRect(surface);
8213 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8214 hr = IDirect3DSurface9_UnlockRect(surface);
8215 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8217 IDirect3DSurface9_Release(surface);
8220 refcount = IDirect3DDevice9_Release(device);
8221 ok(!refcount, "Device has %u references left.\n", refcount);
8222 IDirect3D9_Release(d3d);
8223 DestroyWindow(window);
8226 static void test_surface_blocks(void)
8228 static const struct
8230 D3DFORMAT fmt;
8231 const char *name;
8232 unsigned int block_width;
8233 unsigned int block_height;
8234 BOOL broken;
8235 BOOL create_size_checked, core_fmt;
8237 formats[] =
8239 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8240 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8241 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8242 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8243 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8244 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8245 * which doesn't match the format spec. On newer Nvidia cards
8246 * they have the correct 4x4 block size */
8247 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8248 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8249 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8250 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8252 static const struct
8254 D3DPOOL pool;
8255 const char *name;
8256 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8257 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8258 BOOL success;
8260 pools[] =
8262 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8263 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8264 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8265 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8267 static struct
8269 D3DRESOURCETYPE rtype;
8270 const char *type_name;
8271 D3DPOOL pool;
8272 const char *pool_name;
8273 BOOL need_driver_support, need_runtime_support;
8275 create_tests[] =
8277 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8278 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8279 /* Managed offscreen plain surfaces are not supported */
8280 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8282 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8283 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8284 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8285 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8287 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8288 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8289 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8290 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8292 IDirect3DTexture9 *texture;
8293 IDirect3DCubeTexture9 *cube_texture;
8294 IDirect3DSurface9 *surface;
8295 D3DLOCKED_RECT locked_rect;
8296 IDirect3DDevice9 *device;
8297 unsigned int i, j, k, w, h;
8298 BOOL surface_only;
8299 IDirect3D9 *d3d;
8300 ULONG refcount;
8301 HWND window;
8302 HRESULT hr;
8303 RECT rect;
8304 BOOL tex_pow2, cube_pow2;
8305 D3DCAPS9 caps;
8306 static const RECT invalid[] =
8308 {60, 60, 60, 68}, /* 0 height */
8309 {60, 60, 68, 60}, /* 0 width */
8310 {68, 60, 60, 68}, /* left > right */
8311 {60, 68, 68, 60}, /* top > bottom */
8312 {-8, 60, 0, 68}, /* left < surface */
8313 {60, -8, 68, 0}, /* top < surface */
8314 {-16, 60, -8, 68}, /* right < surface */
8315 {60, -16, 68, -8}, /* bottom < surface */
8316 {60, 60, 136, 68}, /* right > surface */
8317 {60, 60, 68, 136}, /* bottom > surface */
8318 {136, 60, 144, 68}, /* left > surface */
8319 {60, 136, 68, 144}, /* top > surface */
8322 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8323 0, 0, 640, 480, 0, 0, 0, 0);
8324 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8325 ok(!!d3d, "Failed to create a D3D object.\n");
8326 if (!(device = create_device(d3d, window, NULL)))
8328 skip("Failed to create a D3D device, skipping tests.\n");
8329 IDirect3D9_Release(d3d);
8330 DestroyWindow(window);
8331 return;
8334 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8335 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8336 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8337 if (tex_pow2)
8338 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8339 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8341 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
8343 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8345 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8346 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8347 tex_support = SUCCEEDED(hr);
8348 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8349 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8350 cube_support = SUCCEEDED(hr);
8351 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8352 0, D3DRTYPE_SURFACE, formats[i].fmt);
8353 surface_support = SUCCEEDED(hr);
8355 /* Scratch pool in general allows texture creation even if the driver does
8356 * not support the format. If the format is an extension format that is not
8357 * known to the runtime, like ATI2N, some driver support is required for
8358 * this to work.
8360 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8361 * about ATI2N. I cannot check this because all my Vista+ machines support
8362 * ATI2N in hardware, but none of my WinXP machines do. */
8363 format_known = tex_support || cube_support || surface_support;
8365 for (w = 1; w <= 8; w++)
8367 for (h = 1; h <= 8; h++)
8369 BOOL block_aligned = TRUE;
8370 BOOL size_is_pow2;
8372 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8373 block_aligned = FALSE;
8375 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8377 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
8379 BOOL support, pow2;
8380 HRESULT expect_hr;
8381 BOOL may_succeed = FALSE;
8382 IUnknown **check_null;
8384 if (!formats[i].core_fmt)
8386 /* AMD warns against creating ATI2N textures smaller than
8387 * the block size because the runtime cannot calculate the
8388 * correct texture size. Generalize this for all extension
8389 * formats. */
8390 if (w < formats[i].block_width || h < formats[i].block_height)
8391 continue;
8394 texture = (IDirect3DTexture9 *)0xdeadbeef;
8395 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8396 surface = (IDirect3DSurface9 *)0xdeadbeef;
8398 switch (create_tests[j].rtype)
8400 case D3DRTYPE_TEXTURE:
8401 check_null = (IUnknown **)&texture;
8402 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8403 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8404 support = tex_support;
8405 pow2 = tex_pow2;
8406 break;
8408 case D3DRTYPE_CUBETEXTURE:
8409 if (w != h)
8410 continue;
8411 check_null = (IUnknown **)&cube_texture;
8412 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8413 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8414 support = cube_support;
8415 pow2 = cube_pow2;
8416 break;
8418 case D3DRTYPE_SURFACE:
8419 check_null = (IUnknown **)&surface;
8420 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8421 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8422 support = surface_support;
8423 pow2 = FALSE;
8424 break;
8426 default:
8427 check_null = NULL;
8428 pow2 = FALSE;
8429 support = FALSE;
8430 break;
8433 if (create_tests[j].need_driver_support && !support)
8434 expect_hr = D3DERR_INVALIDCALL;
8435 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8436 expect_hr = D3DERR_INVALIDCALL;
8437 else if (formats[i].create_size_checked && !block_aligned)
8438 expect_hr = D3DERR_INVALIDCALL;
8439 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8440 expect_hr = D3DERR_INVALIDCALL;
8441 else
8442 expect_hr = D3D_OK;
8444 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8445 * does not support it. Accept scratch creation of extension formats on
8446 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8447 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8448 * support it. */
8449 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8450 may_succeed = TRUE;
8452 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8453 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8454 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8455 if (FAILED(hr))
8456 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8457 else
8458 IUnknown_Release(*check_null);
8463 surface_only = FALSE;
8464 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8465 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8466 dynamic_tex_support = SUCCEEDED(hr);
8467 if (!dynamic_tex_support)
8469 if (!surface_support)
8471 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8472 continue;
8474 surface_only = TRUE;
8477 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
8479 switch (pools[j].pool)
8481 case D3DPOOL_SYSTEMMEM:
8482 case D3DPOOL_MANAGED:
8483 if (surface_only)
8484 continue;
8485 /* Fall through */
8486 case D3DPOOL_DEFAULT:
8487 if (surface_only)
8489 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8490 formats[i].fmt, pools[j].pool, &surface, NULL);
8491 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8493 else
8495 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8496 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8497 formats[i].fmt, pools[j].pool, &texture, NULL);
8498 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8499 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8500 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8501 IDirect3DTexture9_Release(texture);
8503 break;
8505 case D3DPOOL_SCRATCH:
8506 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8507 formats[i].fmt, pools[j].pool, &surface, NULL);
8508 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8509 break;
8511 default:
8512 break;
8515 if (formats[i].block_width > 1)
8517 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8518 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8519 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8520 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8521 SUCCEEDED(hr) ? "succeeded" : "failed",
8522 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8523 if (SUCCEEDED(hr))
8525 hr = IDirect3DSurface9_UnlockRect(surface);
8526 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8529 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8530 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8531 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8532 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8533 SUCCEEDED(hr) ? "succeeded" : "failed",
8534 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8535 if (SUCCEEDED(hr))
8537 hr = IDirect3DSurface9_UnlockRect(surface);
8538 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8542 if (formats[i].block_height > 1)
8544 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
8545 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8546 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8547 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8548 SUCCEEDED(hr) ? "succeeded" : "failed",
8549 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8550 if (SUCCEEDED(hr))
8552 hr = IDirect3DSurface9_UnlockRect(surface);
8553 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8556 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
8557 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8558 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8559 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8560 SUCCEEDED(hr) ? "succeeded" : "failed",
8561 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8562 if (SUCCEEDED(hr))
8564 hr = IDirect3DSurface9_UnlockRect(surface);
8565 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8569 for (k = 0; k < sizeof(invalid) / sizeof(*invalid); ++k)
8571 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
8572 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
8573 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
8574 formats[i].name, pools[j].name, k);
8575 if (SUCCEEDED(hr))
8577 hr = IDirect3DSurface9_UnlockRect(surface);
8578 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8582 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8583 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8584 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
8585 hr = IDirect3DSurface9_UnlockRect(surface);
8586 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8588 IDirect3DSurface9_Release(surface);
8591 if (!dynamic_tex_support)
8593 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
8594 continue;
8597 if (formats[i].block_width == 1 && formats[i].block_height == 1)
8598 continue;
8599 if (!formats[i].core_fmt)
8600 continue;
8602 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
8603 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
8604 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
8606 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
8607 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8608 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8609 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8611 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
8612 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
8613 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 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, formats[i].block_height);
8619 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8620 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8621 if (SUCCEEDED(hr))
8622 IDirect3DTexture9_UnlockRect(texture, 1);
8624 IDirect3DTexture9_Release(texture);
8627 refcount = IDirect3DDevice9_Release(device);
8628 ok(!refcount, "Device has %u references left.\n", refcount);
8629 IDirect3D9_Release(d3d);
8630 DestroyWindow(window);
8633 static void test_set_palette(void)
8635 IDirect3DDevice9 *device;
8636 IDirect3D9 *d3d9;
8637 UINT refcount;
8638 HWND window;
8639 HRESULT hr;
8640 PALETTEENTRY pal[256];
8641 unsigned int i;
8642 D3DCAPS9 caps;
8644 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8645 0, 0, 640, 480, 0, 0, 0, 0);
8646 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8647 ok(!!d3d9, "Failed to create a D3D object.\n");
8648 if (!(device = create_device(d3d9, window, NULL)))
8650 skip("Failed to create a D3D device, skipping tests.\n");
8651 DestroyWindow(window);
8652 return;
8655 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8657 pal[i].peRed = i;
8658 pal[i].peGreen = i;
8659 pal[i].peBlue = i;
8660 pal[i].peFlags = 0xff;
8662 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8663 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8665 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8666 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8667 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8669 pal[i].peRed = i;
8670 pal[i].peGreen = i;
8671 pal[i].peBlue = i;
8672 pal[i].peFlags = i;
8674 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
8676 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8677 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8679 else
8681 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8682 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
8685 refcount = IDirect3DDevice9_Release(device);
8686 ok(!refcount, "Device has %u references left.\n", refcount);
8687 IDirect3D9_Release(d3d9);
8688 DestroyWindow(window);
8691 static void test_swvp_buffer(void)
8693 IDirect3DDevice9 *device;
8694 IDirect3D9 *d3d9;
8695 UINT refcount;
8696 HWND window;
8697 HRESULT hr;
8698 unsigned int i;
8699 IDirect3DVertexBuffer9 *buffer;
8700 static const unsigned int bufsize = 1024;
8701 D3DVERTEXBUFFER_DESC desc;
8702 struct device_desc device_desc;
8703 struct
8705 float x, y, z;
8706 } *ptr, *ptr2;
8708 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8709 0, 0, 640, 480, 0, 0, 0, 0);
8710 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8711 ok(!!d3d9, "Failed to create a D3D object.\n");
8713 device_desc.device_window = window;
8714 device_desc.width = 640;
8715 device_desc.height = 480;
8716 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
8717 if (!(device = create_device(d3d9, window, &device_desc)))
8719 skip("Failed to create a D3D device, skipping tests.\n");
8720 DestroyWindow(window);
8721 IDirect3D9_Release(d3d9);
8722 return;
8725 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
8726 D3DPOOL_DEFAULT, &buffer, NULL);
8727 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8728 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8729 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8730 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
8731 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
8732 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
8734 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8735 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8736 for (i = 0; i < bufsize; i++)
8738 ptr[i].x = i * 1.0f;
8739 ptr[i].y = i * 2.0f;
8740 ptr[i].z = i * 3.0f;
8742 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8743 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8745 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8746 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8747 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8748 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8749 hr = IDirect3DDevice9_BeginScene(device);
8750 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8751 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8752 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8753 hr = IDirect3DDevice9_EndScene(device);
8754 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8756 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8757 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8758 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
8759 for (i = 0; i < bufsize; i++)
8761 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8763 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
8764 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8765 break;
8768 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8769 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8771 IDirect3DVertexBuffer9_Release(buffer);
8772 refcount = IDirect3DDevice9_Release(device);
8773 ok(!refcount, "Device has %u references left.\n", refcount);
8774 IDirect3D9_Release(d3d9);
8775 DestroyWindow(window);
8778 static void test_managed_buffer(void)
8780 static const unsigned int vertex_count = 1024;
8781 IDirect3DVertexBuffer9 *buffer;
8782 D3DVERTEXBUFFER_DESC desc;
8783 IDirect3DDevice9 *device;
8784 struct vec3 *ptr, *ptr2;
8785 IDirect3D9 *d3d9;
8786 unsigned int i;
8787 UINT refcount;
8788 HWND window;
8789 HRESULT hr;
8791 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8792 0, 0, 640, 480, 0, 0, 0, 0);
8793 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8794 ok(!!d3d9, "Failed to create a D3D object.\n");
8795 if (!(device = create_device(d3d9, window, NULL)))
8797 skip("Failed to create a D3D device, skipping tests.\n");
8798 IDirect3D9_Release(d3d9);
8799 DestroyWindow(window);
8800 return;
8803 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
8804 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
8805 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8806 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8807 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8808 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
8809 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
8811 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8812 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8813 for (i = 0; i < vertex_count; ++i)
8815 ptr[i].x = i * 1.0f;
8816 ptr[i].y = i * 2.0f;
8817 ptr[i].z = i * 3.0f;
8819 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8820 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8822 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8823 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8824 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8825 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8826 hr = IDirect3DDevice9_BeginScene(device);
8827 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8828 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8829 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8830 hr = IDirect3DDevice9_EndScene(device);
8831 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8833 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8834 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8835 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
8836 for (i = 0; i < vertex_count; ++i)
8838 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8840 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
8841 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8842 break;
8845 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8846 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8848 IDirect3DVertexBuffer9_Release(buffer);
8849 refcount = IDirect3DDevice9_Release(device);
8850 ok(!refcount, "Device has %u references left.\n", refcount);
8851 IDirect3D9_Release(d3d9);
8852 DestroyWindow(window);
8855 static void test_npot_textures(void)
8857 IDirect3DDevice9 *device = NULL;
8858 IDirect3D9 *d3d9;
8859 ULONG refcount;
8860 HWND window = NULL;
8861 HRESULT hr;
8862 D3DCAPS9 caps;
8863 IDirect3DTexture9 *texture;
8864 IDirect3DCubeTexture9 *cube_texture;
8865 IDirect3DVolumeTexture9 *volume_texture;
8866 struct
8868 D3DPOOL pool;
8869 const char *pool_name;
8870 HRESULT hr;
8872 pools[] =
8874 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
8875 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
8876 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
8877 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
8879 unsigned int i, levels;
8880 BOOL tex_pow2, cube_pow2, vol_pow2;
8882 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8883 0, 0, 640, 480, 0, 0, 0, 0);
8884 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8885 ok(!!d3d9, "Failed to create a D3D object.\n");
8886 if (!(device = create_device(d3d9, window, NULL)))
8888 skip("Failed to create a D3D device, skipping tests.\n");
8889 goto done;
8892 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8893 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8894 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8895 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8896 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8897 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
8898 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
8900 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
8902 for (levels = 0; levels <= 2; levels++)
8904 HRESULT expected;
8906 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
8907 pools[i].pool, &texture, NULL);
8908 if (!tex_pow2)
8910 expected = D3D_OK;
8912 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
8914 if (levels == 1)
8915 expected = D3D_OK;
8916 else
8917 expected = pools[i].hr;
8919 else
8921 expected = pools[i].hr;
8923 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
8924 pools[i].pool_name, levels, hr, expected);
8926 if (SUCCEEDED(hr))
8927 IDirect3DTexture9_Release(texture);
8930 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8931 &cube_texture, NULL);
8932 if (tex_pow2)
8934 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8935 pools[i].pool_name, hr, pools[i].hr);
8937 else
8939 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8940 pools[i].pool_name, hr, D3D_OK);
8943 if (SUCCEEDED(hr))
8944 IDirect3DCubeTexture9_Release(cube_texture);
8946 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8947 &volume_texture, NULL);
8948 if (tex_pow2)
8950 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8951 pools[i].pool_name, hr, pools[i].hr);
8953 else
8955 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8956 pools[i].pool_name, hr, D3D_OK);
8959 if (SUCCEEDED(hr))
8960 IDirect3DVolumeTexture9_Release(volume_texture);
8963 done:
8964 if (device)
8966 refcount = IDirect3DDevice9_Release(device);
8967 ok(!refcount, "Device has %u references left.\n", refcount);
8969 IDirect3D9_Release(d3d9);
8970 DestroyWindow(window);
8974 static void test_vidmem_accounting(void)
8976 IDirect3DDevice9 *device;
8977 IDirect3D9 *d3d9;
8978 ULONG refcount;
8979 HWND window;
8980 HRESULT hr = D3D_OK;
8981 IDirect3DTexture9 *textures[20];
8982 unsigned int i;
8983 UINT vidmem_start, vidmem_end, diff;
8985 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8986 0, 0, 640, 480, 0, 0, 0, 0);
8987 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8988 ok(!!d3d9, "Failed to create a D3D object.\n");
8989 if (!(device = create_device(d3d9, window, NULL)))
8991 skip("Failed to create a D3D device, skipping tests.\n");
8992 IDirect3D9_Release(d3d9);
8993 DestroyWindow(window);
8994 return;
8997 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
8998 memset(textures, 0, sizeof(textures));
8999 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
9001 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9002 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9003 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9004 * E_FAIL is returned on address space or system memory exhaustion */
9005 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9006 "Failed to create texture, hr %#x.\n", hr);
9008 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9010 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9011 diff = vidmem_start - vidmem_end;
9012 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9013 2 * i, diff / 1024 / 1024);
9015 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
9017 if (textures[i])
9018 IDirect3DTexture9_Release(textures[i]);
9021 refcount = IDirect3DDevice9_Release(device);
9022 ok(!refcount, "Device has %u references left.\n", refcount);
9023 IDirect3D9_Release(d3d9);
9024 DestroyWindow(window);
9027 static void test_volume_locking(void)
9029 IDirect3DDevice9 *device;
9030 IDirect3D9 *d3d9;
9031 HWND window;
9032 HRESULT hr;
9033 IDirect3DVolumeTexture9 *texture;
9034 unsigned int i;
9035 D3DLOCKED_BOX locked_box;
9036 ULONG refcount;
9037 D3DCAPS9 caps;
9038 static const struct
9040 D3DPOOL pool;
9041 DWORD usage;
9042 HRESULT create_hr, lock_hr;
9044 tests[] =
9046 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9047 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9048 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9049 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9050 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9051 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9052 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9053 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9056 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9057 0, 0, 640, 480, 0, 0, 0, 0);
9058 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9059 ok(!!d3d9, "Failed to create a D3D object.\n");
9060 if (!(device = create_device(d3d9, window, NULL)))
9062 skip("Failed to create a D3D device, skipping tests.\n");
9063 IDirect3D9_Release(d3d9);
9064 DestroyWindow(window);
9065 return;
9068 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9069 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9070 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9072 skip("Volume textures not supported, skipping test.\n");
9073 goto out;
9076 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9078 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9079 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9080 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9081 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9082 if (FAILED(hr))
9083 continue;
9085 locked_box.pBits = (void *)0xdeadbeef;
9086 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9087 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9088 if (SUCCEEDED(hr))
9090 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9091 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9093 else
9095 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9097 IDirect3DVolumeTexture9_Release(texture);
9100 out:
9101 refcount = IDirect3DDevice9_Release(device);
9102 ok(!refcount, "Device has %u references left.\n", refcount);
9103 IDirect3D9_Release(d3d9);
9104 DestroyWindow(window);
9107 static void test_update_volumetexture(void)
9109 IDirect3DDevice9 *device;
9110 IDirect3D9 *d3d9;
9111 HWND window;
9112 HRESULT hr;
9113 IDirect3DVolumeTexture9 *src, *dst;
9114 unsigned int i;
9115 D3DLOCKED_BOX locked_box;
9116 ULONG refcount;
9117 D3DCAPS9 caps;
9118 static const struct
9120 D3DPOOL src_pool, dst_pool;
9121 HRESULT hr;
9123 tests[] =
9125 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9126 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9127 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9128 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9130 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9131 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9132 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9133 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9135 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9136 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9137 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9138 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9140 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9141 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9142 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9143 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9145 static const struct
9147 UINT src_size, dst_size;
9148 UINT src_lvl, dst_lvl;
9149 D3DFORMAT src_fmt, dst_fmt;
9151 tests2[] =
9153 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9154 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9155 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9156 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9157 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9158 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9159 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9160 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9163 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9164 0, 0, 640, 480, 0, 0, 0, 0);
9165 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9166 ok(!!d3d9, "Failed to create a D3D object.\n");
9167 if (!(device = create_device(d3d9, window, NULL)))
9169 skip("Failed to create a D3D device, skipping tests.\n");
9170 IDirect3D9_Release(d3d9);
9171 DestroyWindow(window);
9172 return;
9175 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9176 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9177 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9179 skip("Volume textures not supported, skipping test.\n");
9180 goto out;
9183 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9185 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9186 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9188 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9189 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9190 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9191 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9192 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9193 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9195 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9196 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9197 *((DWORD *)locked_box.pBits) = 0x11223344;
9198 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9199 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9201 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9202 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9203 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9205 if (SUCCEEDED(hr))
9207 DWORD content = *((DWORD *)locked_box.pBits);
9208 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9209 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9210 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9211 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9212 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9214 IDirect3DVolumeTexture9_Release(src);
9215 IDirect3DVolumeTexture9_Release(dst);
9218 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9220 skip("Mipmapped volume maps not supported.\n");
9221 goto out;
9224 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
9226 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9227 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9228 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9229 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9230 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9231 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9232 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9233 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9235 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9236 todo_wine_if (FAILED(hr))
9237 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9239 IDirect3DVolumeTexture9_Release(src);
9240 IDirect3DVolumeTexture9_Release(dst);
9243 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9244 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9245 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9246 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9247 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9249 * I'm not adding tests for this behavior until an application needs it. */
9251 out:
9252 refcount = IDirect3DDevice9_Release(device);
9253 ok(!refcount, "Device has %u references left.\n", refcount);
9254 IDirect3D9_Release(d3d9);
9255 DestroyWindow(window);
9258 static void test_create_rt_ds_fail(void)
9260 IDirect3DDevice9 *device;
9261 HWND window;
9262 HRESULT hr;
9263 ULONG refcount;
9264 IDirect3D9 *d3d9;
9265 IDirect3DSurface9 *surface;
9267 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9268 0, 0, 640, 480, 0, 0, 0, 0);
9269 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9270 ok(!!d3d9, "Failed to create a D3D object.\n");
9271 if (!(device = create_device(d3d9, window, NULL)))
9273 skip("Failed to create a D3D device, skipping tests.\n");
9274 IDirect3D9_Release(d3d9);
9275 DestroyWindow(window);
9276 return;
9279 /* Output pointer == NULL segfaults on Windows. */
9281 surface = (IDirect3DSurface9 *)0xdeadbeef;
9282 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9283 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9284 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9285 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9286 if (SUCCEEDED(hr))
9287 IDirect3DSurface9_Release(surface);
9289 surface = (IDirect3DSurface9 *)0xdeadbeef;
9290 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9291 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9292 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9293 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9294 if (SUCCEEDED(hr))
9295 IDirect3DSurface9_Release(surface);
9297 refcount = IDirect3DDevice9_Release(device);
9298 ok(!refcount, "Device has %u references left.\n", refcount);
9299 IDirect3D9_Release(d3d9);
9300 DestroyWindow(window);
9303 static void test_volume_blocks(void)
9305 IDirect3DDevice9 *device;
9306 IDirect3D9 *d3d9;
9307 UINT refcount;
9308 HWND window;
9309 HRESULT hr;
9310 D3DCAPS9 caps;
9311 IDirect3DVolumeTexture9 *texture;
9312 unsigned int w, h, d, i, j;
9313 static const struct
9315 D3DFORMAT fmt;
9316 const char *name;
9317 unsigned int block_width;
9318 unsigned int block_height;
9319 unsigned int block_depth;
9320 unsigned int block_size;
9321 unsigned int broken;
9322 BOOL create_size_checked, core_fmt;
9324 formats[] =
9326 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9327 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9328 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9329 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9330 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9331 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9332 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9333 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9334 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9335 * which doesn't match the format spec. On newer Nvidia cards
9336 * it has the correct 4x4 block size.
9337 * ATI1N volume textures are only supported by AMD GPUs right
9338 * now and locking offsets seem just wrong. */
9339 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9340 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9341 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9342 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9344 static const struct
9346 D3DPOOL pool;
9347 const char *name;
9348 BOOL need_driver_support, need_runtime_support;
9350 create_tests[] =
9352 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9353 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9354 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9355 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9357 static const struct
9359 unsigned int x, y, z, x2, y2, z2;
9361 offset_tests[] =
9363 {0, 0, 0, 8, 8, 8},
9364 {0, 0, 3, 8, 8, 8},
9365 {0, 4, 0, 8, 8, 8},
9366 {0, 4, 3, 8, 8, 8},
9367 {4, 0, 0, 8, 8, 8},
9368 {4, 0, 3, 8, 8, 8},
9369 {4, 4, 0, 8, 8, 8},
9370 {4, 4, 3, 8, 8, 8},
9372 D3DBOX box;
9373 D3DLOCKED_BOX locked_box;
9374 BYTE *base;
9375 INT expected_row_pitch, expected_slice_pitch;
9376 BOOL support;
9377 BOOL pow2;
9378 unsigned int offset, expected_offset;
9380 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9381 0, 0, 640, 480, 0, 0, 0, 0);
9382 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9383 ok(!!d3d9, "Failed to create a D3D object.\n");
9384 if (!(device = create_device(d3d9, window, NULL)))
9386 skip("Failed to create a D3D device, skipping tests.\n");
9387 IDirect3D9_Release(d3d9);
9388 DestroyWindow(window);
9389 return;
9391 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9392 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9393 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9395 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
9397 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9398 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9399 support = SUCCEEDED(hr);
9401 /* Test creation restrictions */
9402 for (w = 1; w <= 8; w++)
9404 for (h = 1; h <= 8; h++)
9406 for (d = 1; d <= 8; d++)
9408 HRESULT expect_hr;
9409 BOOL size_is_pow2;
9410 BOOL block_aligned = TRUE;
9412 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9413 block_aligned = FALSE;
9415 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9417 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
9419 BOOL may_succeed = FALSE;
9421 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9422 expect_hr = D3DERR_INVALIDCALL;
9423 else if (formats[i].create_size_checked && !block_aligned)
9424 expect_hr = D3DERR_INVALIDCALL;
9425 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9426 expect_hr = D3DERR_INVALIDCALL;
9427 else if (create_tests[j].need_driver_support && !support)
9428 expect_hr = D3DERR_INVALIDCALL;
9429 else
9430 expect_hr = D3D_OK;
9432 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9433 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9434 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9436 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9437 * does not support it. Accept scratch creation of extension formats on
9438 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9439 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9440 * support it. */
9441 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9442 may_succeed = TRUE;
9444 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9445 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9446 hr, formats[i].name, create_tests[j].name, w, h, d);
9448 if (FAILED(hr))
9449 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9450 else
9451 IDirect3DVolumeTexture9_Release(texture);
9457 if (!support && !formats[i].core_fmt)
9458 continue;
9460 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9461 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9462 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9464 /* Test lockrect offset */
9465 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
9467 unsigned int bytes_per_pixel;
9468 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9470 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9471 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9473 base = locked_box.pBits;
9474 if (formats[i].broken == 1)
9476 expected_row_pitch = bytes_per_pixel * 24;
9478 else if (formats[i].broken == 2)
9480 expected_row_pitch = 24;
9482 else
9484 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9485 * formats[i].block_size;
9487 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9488 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9490 if (formats[i].broken)
9492 expected_slice_pitch = expected_row_pitch * 8;
9494 else
9496 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9497 * expected_row_pitch;
9499 ok(locked_box.SlicePitch == expected_slice_pitch,
9500 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9501 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9503 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9504 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9506 box.Left = offset_tests[j].x;
9507 box.Top = offset_tests[j].y;
9508 box.Front = offset_tests[j].z;
9509 box.Right = offset_tests[j].x2;
9510 box.Bottom = offset_tests[j].y2;
9511 box.Back = offset_tests[j].z2;
9512 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9513 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9515 offset = (BYTE *)locked_box.pBits - base;
9516 if (formats[i].broken == 1)
9518 expected_offset = box.Front * expected_slice_pitch
9519 + box.Top * expected_row_pitch
9520 + box.Left * bytes_per_pixel;
9522 else if (formats[i].broken == 2)
9524 expected_offset = box.Front * expected_slice_pitch
9525 + box.Top * expected_row_pitch
9526 + box.Left;
9528 else
9530 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9531 + (box.Top / formats[i].block_height) * expected_row_pitch
9532 + (box.Left / formats[i].block_width) * formats[i].block_size;
9534 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9535 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9537 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9538 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9541 /* Test partial block locks */
9542 box.Front = 0;
9543 box.Back = 1;
9544 if (formats[i].block_width > 1)
9546 box.Left = formats[i].block_width >> 1;
9547 box.Top = 0;
9548 box.Right = formats[i].block_width;
9549 box.Bottom = formats[i].block_height;
9550 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9551 ok(FAILED(hr) || broken(formats[i].broken),
9552 "Partial block lock succeeded, expected failure, format %s.\n",
9553 formats[i].name);
9554 if (SUCCEEDED(hr))
9556 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9557 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9560 box.Left = 0;
9561 box.Top = 0;
9562 box.Right = formats[i].block_width >> 1;
9563 box.Bottom = formats[i].block_height;
9564 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9565 ok(FAILED(hr) || broken(formats[i].broken),
9566 "Partial block lock succeeded, expected failure, format %s.\n",
9567 formats[i].name);
9568 if (SUCCEEDED(hr))
9570 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9571 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9575 if (formats[i].block_height > 1)
9577 box.Left = 0;
9578 box.Top = formats[i].block_height >> 1;
9579 box.Right = formats[i].block_width;
9580 box.Bottom = formats[i].block_height;
9581 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9582 ok(FAILED(hr) || broken(formats[i].broken),
9583 "Partial block lock succeeded, expected failure, format %s.\n",
9584 formats[i].name);
9585 if (SUCCEEDED(hr))
9587 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9588 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9591 box.Left = 0;
9592 box.Top = 0;
9593 box.Right = formats[i].block_width;
9594 box.Bottom = formats[i].block_height >> 1;
9595 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9596 ok(FAILED(hr) || broken(formats[i].broken),
9597 "Partial block lock succeeded, expected failure, format %s.\n",
9598 formats[i].name);
9599 if (SUCCEEDED(hr))
9601 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9602 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9606 /* Test full block lock */
9607 box.Left = 0;
9608 box.Top = 0;
9609 box.Right = formats[i].block_width;
9610 box.Bottom = formats[i].block_height;
9611 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9612 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9613 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9614 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9616 IDirect3DVolumeTexture9_Release(texture);
9618 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
9619 * does not allocate surfaces smaller than the blocksize properly. */
9620 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
9622 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
9623 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9624 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9626 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
9627 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9628 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9629 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9631 box.Left = box.Top = box.Front = 0;
9632 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
9633 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
9634 box.Back = 1;
9635 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9636 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9637 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9638 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9640 box.Right = formats[i].block_width;
9641 box.Bottom = formats[i].block_height;
9642 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9643 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9644 if (SUCCEEDED(hr))
9645 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9647 IDirect3DVolumeTexture9_Release(texture);
9651 refcount = IDirect3DDevice9_Release(device);
9652 ok(!refcount, "Device has %u references left.\n", refcount);
9653 IDirect3D9_Release(d3d9);
9654 DestroyWindow(window);
9657 static void test_lockbox_invalid(void)
9659 static const struct
9661 D3DBOX box;
9662 HRESULT result;
9664 test_data[] =
9666 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
9667 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
9668 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
9669 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
9670 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
9671 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
9672 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
9673 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
9674 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
9675 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
9676 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
9677 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
9678 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
9679 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
9681 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
9682 IDirect3DVolumeTexture9 *texture = NULL;
9683 D3DLOCKED_BOX locked_box;
9684 IDirect3DDevice9 *device;
9685 IDirect3D9 *d3d;
9686 unsigned int i;
9687 ULONG refcount;
9688 HWND window;
9689 BYTE *base;
9690 HRESULT hr;
9692 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9693 0, 0, 640, 480, 0, 0, 0, 0);
9694 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9695 ok(!!d3d, "Failed to create a D3D object.\n");
9696 if (!(device = create_device(d3d, window, NULL)))
9698 skip("Failed to create a D3D device, skipping tests.\n");
9699 IDirect3D9_Release(d3d);
9700 DestroyWindow(window);
9701 return;
9704 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
9705 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
9706 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9707 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9708 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9709 base = locked_box.pBits;
9710 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9711 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9713 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
9715 unsigned int offset, expected_offset;
9716 const D3DBOX *box = &test_data[i].box;
9718 locked_box.pBits = (BYTE *)0xdeadbeef;
9719 locked_box.RowPitch = 0xdeadbeef;
9720 locked_box.SlicePitch = 0xdeadbeef;
9722 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
9723 /* Unlike surfaces, volumes properly check the box even in Windows XP */
9724 ok(hr == test_data[i].result,
9725 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
9726 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
9727 test_data[i].result);
9728 if (FAILED(hr))
9729 continue;
9731 offset = (BYTE *)locked_box.pBits - base;
9732 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
9733 ok(offset == expected_offset,
9734 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
9735 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
9737 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9738 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9741 /* locked_box = NULL throws an exception on Windows */
9742 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9743 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9744 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9745 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9746 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9747 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9748 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9749 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9751 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9752 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9753 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9754 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9755 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9756 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9757 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9758 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9759 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
9760 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9761 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
9762 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
9763 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9764 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9766 IDirect3DVolumeTexture9_Release(texture);
9767 refcount = IDirect3DDevice9_Release(device);
9768 ok(!refcount, "Device has %u references left.\n", refcount);
9769 IDirect3D9_Release(d3d);
9770 DestroyWindow(window);
9773 static void test_shared_handle(void)
9775 IDirect3DDevice9 *device;
9776 IDirect3D9 *d3d;
9777 ULONG refcount;
9778 HWND window;
9779 HRESULT hr;
9780 /* Native d3d9ex refuses to create a shared texture if the texture pointer
9781 * is not initialized to NULL. Make sure this doesn't cause issues here. */
9782 IDirect3DTexture9 *texture = NULL;
9783 IDirect3DSurface9 *surface = NULL;
9784 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
9785 IDirect3DIndexBuffer9 *index_buffer = NULL;
9786 HANDLE handle = NULL;
9787 void *mem;
9788 D3DCAPS9 caps;
9790 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9791 0, 0, 640, 480, 0, 0, 0, 0);
9792 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9793 ok(!!d3d, "Failed to create a D3D object.\n");
9794 if (!(device = create_device(d3d, window, NULL)))
9796 skip("Failed to create a D3D device, skipping tests.\n");
9797 IDirect3D9_Release(d3d);
9798 DestroyWindow(window);
9799 return;
9802 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9803 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9804 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
9806 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
9807 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
9808 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9809 D3DPOOL_DEFAULT, &texture, &handle);
9810 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9811 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9812 D3DPOOL_SYSTEMMEM, &texture, &mem);
9813 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9815 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9816 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
9817 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9818 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9819 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
9820 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9822 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9823 &vertex_buffer, &handle);
9824 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9825 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9826 &vertex_buffer, &mem);
9827 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
9829 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9830 &index_buffer, &handle);
9831 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9832 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9833 &index_buffer, &mem);
9834 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9836 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9838 IDirect3DCubeTexture9 *cube_texture = NULL;
9839 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9840 D3DPOOL_DEFAULT, &cube_texture, &handle);
9841 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9842 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9843 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
9844 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9847 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
9849 IDirect3DVolumeTexture9 *volume_texture = NULL;
9850 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9851 D3DPOOL_DEFAULT, &volume_texture, &handle);
9852 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9853 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9854 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
9855 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9858 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
9859 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9860 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9862 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
9863 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9864 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9866 HeapFree(GetProcessHeap(), 0, mem);
9867 refcount = IDirect3DDevice9_Release(device);
9868 ok(!refcount, "Device has %u references left.\n", refcount);
9869 IDirect3D9_Release(d3d);
9870 DestroyWindow(window);
9873 static void test_pixel_format(void)
9875 HWND hwnd, hwnd2 = NULL;
9876 HDC hdc, hdc2 = NULL;
9877 HMODULE gl = NULL;
9878 int format, test_format;
9879 PIXELFORMATDESCRIPTOR pfd;
9880 IDirect3D9 *d3d9 = NULL;
9881 IDirect3DDevice9 *device = NULL;
9882 HRESULT hr;
9883 static const float point[3] = {0.0, 0.0, 0.0};
9885 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9886 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9887 if (!hwnd)
9889 skip("Failed to create window\n");
9890 return;
9893 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9894 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9896 hdc = GetDC(hwnd);
9897 if (!hdc)
9899 skip("Failed to get DC\n");
9900 goto cleanup;
9903 if (hwnd2)
9904 hdc2 = GetDC(hwnd2);
9906 gl = LoadLibraryA("opengl32.dll");
9907 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
9909 format = GetPixelFormat(hdc);
9910 ok(format == 0, "new window has pixel format %d\n", format);
9912 ZeroMemory(&pfd, sizeof(pfd));
9913 pfd.nSize = sizeof(pfd);
9914 pfd.nVersion = 1;
9915 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
9916 pfd.iPixelType = PFD_TYPE_RGBA;
9917 pfd.iLayerType = PFD_MAIN_PLANE;
9918 format = ChoosePixelFormat(hdc, &pfd);
9919 if (format <= 0)
9921 skip("no pixel format available\n");
9922 goto cleanup;
9925 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
9927 skip("failed to set pixel format\n");
9928 goto cleanup;
9931 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
9933 skip("failed to set pixel format on second window\n");
9934 if (hdc2)
9936 ReleaseDC(hwnd2, hdc2);
9937 hdc2 = NULL;
9941 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9942 ok(!!d3d9, "Failed to create a D3D object.\n");
9944 test_format = GetPixelFormat(hdc);
9945 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9947 if (!(device = create_device(d3d9, hwnd, NULL)))
9949 skip("Failed to create device\n");
9950 goto cleanup;
9953 test_format = GetPixelFormat(hdc);
9954 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9956 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9957 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
9959 test_format = GetPixelFormat(hdc);
9960 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9962 hr = IDirect3DDevice9_BeginScene(device);
9963 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
9965 test_format = GetPixelFormat(hdc);
9966 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9968 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
9969 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9971 test_format = GetPixelFormat(hdc);
9972 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9974 hr = IDirect3DDevice9_EndScene(device);
9975 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
9977 test_format = GetPixelFormat(hdc);
9978 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9980 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9981 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9983 test_format = GetPixelFormat(hdc);
9984 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9986 if (hdc2)
9988 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
9989 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9991 test_format = GetPixelFormat(hdc);
9992 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9994 test_format = GetPixelFormat(hdc2);
9995 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
9998 cleanup:
9999 if (device)
10001 UINT refcount = IDirect3DDevice9_Release(device);
10002 ok(!refcount, "Device has %u references left.\n", refcount);
10004 if (d3d9) IDirect3D9_Release(d3d9);
10005 if (gl) FreeLibrary(gl);
10006 if (hdc) ReleaseDC(hwnd, hdc);
10007 if (hdc2) ReleaseDC(hwnd2, hdc2);
10008 if (hwnd) DestroyWindow(hwnd);
10009 if (hwnd2) DestroyWindow(hwnd2);
10012 static void test_begin_end_state_block(void)
10014 IDirect3DStateBlock9 *stateblock;
10015 IDirect3DDevice9 *device;
10016 IDirect3D9 *d3d;
10017 ULONG refcount;
10018 HWND window;
10019 HRESULT hr;
10021 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10022 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10023 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10024 ok(!!d3d, "Failed to create a D3D object.\n");
10025 if (!(device = create_device(d3d, window, NULL)))
10027 skip("Failed to create a D3D device, skipping tests.\n");
10028 IDirect3D9_Release(d3d);
10029 DestroyWindow(window);
10030 return;
10033 /* Should succeed. */
10034 hr = IDirect3DDevice9_BeginStateBlock(device);
10035 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10037 /* Calling BeginStateBlock() while recording should return
10038 * D3DERR_INVALIDCALL. */
10039 hr = IDirect3DDevice9_BeginStateBlock(device);
10040 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10042 /* Should succeed. */
10043 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10044 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10045 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10046 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10047 "Got unexpected stateblock %p.\n", stateblock);
10048 IDirect3DStateBlock9_Release(stateblock);
10050 /* Calling EndStateBlock() while not recording should return
10051 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10052 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10053 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10054 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10055 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10056 "Got unexpected stateblock %p.\n", stateblock);
10058 refcount = IDirect3DDevice9_Release(device);
10059 ok(!refcount, "Device has %u references left.\n", refcount);
10060 IDirect3D9_Release(d3d);
10061 DestroyWindow(window);
10064 static void test_shader_constant_apply(void)
10066 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10067 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10068 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10069 IDirect3DStateBlock9 *stateblock;
10070 DWORD vs_version, ps_version;
10071 IDirect3DDevice9 *device;
10072 IDirect3D9 *d3d;
10073 ULONG refcount;
10074 D3DCAPS9 caps;
10075 float ret[4];
10076 HWND window;
10077 HRESULT hr;
10079 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10080 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10081 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10082 ok(!!d3d, "Failed to create a D3D object.\n");
10083 if (!(device = create_device(d3d, window, NULL)))
10085 skip("Failed to create a D3D device, skipping tests.\n");
10086 IDirect3D9_Release(d3d);
10087 DestroyWindow(window);
10088 return;
10091 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10092 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10093 vs_version = caps.VertexShaderVersion & 0xffff;
10094 ps_version = caps.PixelShaderVersion & 0xffff;
10096 if (vs_version)
10098 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10099 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10100 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10101 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10103 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10104 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10105 ok(!memcmp(ret, initial, sizeof(initial)),
10106 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10107 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10108 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10109 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10110 ok(!memcmp(ret, initial, sizeof(initial)),
10111 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10112 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10114 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10115 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10117 if (ps_version)
10119 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10120 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10121 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10122 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10124 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10125 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10126 ok(!memcmp(ret, initial, sizeof(initial)),
10127 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10128 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10129 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10130 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10131 ok(!memcmp(ret, initial, sizeof(initial)),
10132 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10133 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10135 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10136 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10139 hr = IDirect3DDevice9_BeginStateBlock(device);
10140 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10142 if (vs_version)
10144 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10145 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10147 if (ps_version)
10149 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10150 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10153 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10154 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10156 if (vs_version)
10158 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10159 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10160 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10161 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10162 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10163 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10164 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10165 ok(!memcmp(ret, initial, sizeof(initial)),
10166 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10167 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10169 if (ps_version)
10171 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10172 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10173 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10174 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10175 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10176 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10177 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10178 ok(!memcmp(ret, initial, sizeof(initial)),
10179 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10180 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10183 /* Apply doesn't overwrite constants that aren't explicitly set on the
10184 * source stateblock. */
10185 hr = IDirect3DStateBlock9_Apply(stateblock);
10186 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10188 if (vs_version)
10190 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10191 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10192 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10193 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10194 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10195 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10196 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10197 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10198 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10199 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10201 if (ps_version)
10203 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10204 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10205 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10206 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10207 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10208 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10209 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10210 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10211 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10212 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10215 IDirect3DStateBlock9_Release(stateblock);
10216 refcount = IDirect3DDevice9_Release(device);
10217 ok(!refcount, "Device has %u references left.\n", refcount);
10218 IDirect3D9_Release(d3d);
10219 DestroyWindow(window);
10222 static void test_vdecl_apply(void)
10224 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10225 IDirect3DStateBlock9 *stateblock;
10226 IDirect3DDevice9 *device;
10227 IDirect3D9 *d3d;
10228 ULONG refcount;
10229 HWND window;
10230 HRESULT hr;
10232 static const D3DVERTEXELEMENT9 decl1[] =
10234 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10235 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10236 D3DDECL_END(),
10239 static const D3DVERTEXELEMENT9 decl2[] =
10241 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10242 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10243 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10244 D3DDECL_END(),
10247 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10248 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10249 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10250 ok(!!d3d, "Failed to create a D3D object.\n");
10251 if (!(device = create_device(d3d, window, NULL)))
10253 skip("Failed to create a D3D device, skipping tests.\n");
10254 IDirect3D9_Release(d3d);
10255 DestroyWindow(window);
10256 return;
10259 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10260 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10262 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10263 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10265 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10266 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10267 hr = IDirect3DDevice9_BeginStateBlock(device);
10268 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10269 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10270 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10271 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10272 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10273 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10274 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10275 hr = IDirect3DStateBlock9_Apply(stateblock);
10276 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10277 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10278 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10279 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10280 declaration, declaration1);
10281 IDirect3DVertexDeclaration9_Release(declaration);
10283 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10284 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10285 hr = IDirect3DStateBlock9_Capture(stateblock);
10286 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10287 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10288 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10289 hr = IDirect3DStateBlock9_Apply(stateblock);
10290 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10291 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10292 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10293 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10294 declaration, declaration2);
10295 IDirect3DVertexDeclaration9_Release(declaration);
10297 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10298 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10299 hr = IDirect3DStateBlock9_Capture(stateblock);
10300 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10301 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10302 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10303 hr = IDirect3DStateBlock9_Apply(stateblock);
10304 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10305 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10306 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10307 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10308 declaration, declaration2);
10309 IDirect3DVertexDeclaration9_Release(declaration);
10311 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10312 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10313 hr = IDirect3DStateBlock9_Capture(stateblock);
10314 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10315 hr = IDirect3DStateBlock9_Apply(stateblock);
10316 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10317 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10318 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10319 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10321 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10322 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10323 hr = IDirect3DStateBlock9_Capture(stateblock);
10324 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10325 hr = IDirect3DStateBlock9_Apply(stateblock);
10326 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10327 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10328 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10329 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10330 declaration, declaration2);
10331 IDirect3DVertexDeclaration9_Release(declaration);
10333 IDirect3DStateBlock9_Release(stateblock);
10334 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10335 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10336 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10337 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10338 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10339 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10340 hr = IDirect3DStateBlock9_Apply(stateblock);
10341 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10342 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10343 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10344 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10345 declaration, declaration1);
10346 IDirect3DVertexDeclaration9_Release(declaration);
10348 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10349 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10350 hr = IDirect3DStateBlock9_Capture(stateblock);
10351 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10352 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10353 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10354 hr = IDirect3DStateBlock9_Apply(stateblock);
10355 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10356 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10357 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10358 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10359 declaration, declaration2);
10360 IDirect3DVertexDeclaration9_Release(declaration);
10362 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10363 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10364 hr = IDirect3DStateBlock9_Capture(stateblock);
10365 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10366 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10367 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10368 hr = IDirect3DStateBlock9_Apply(stateblock);
10369 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10370 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10371 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10372 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10373 declaration, declaration2);
10374 IDirect3DVertexDeclaration9_Release(declaration);
10376 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10377 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10378 hr = IDirect3DStateBlock9_Capture(stateblock);
10379 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10380 hr = IDirect3DStateBlock9_Apply(stateblock);
10381 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10382 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10383 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10384 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10386 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10387 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10388 hr = IDirect3DStateBlock9_Capture(stateblock);
10389 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10390 hr = IDirect3DStateBlock9_Apply(stateblock);
10391 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10392 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10393 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10394 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10395 declaration, declaration2);
10396 IDirect3DVertexDeclaration9_Release(declaration);
10398 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10399 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10400 IDirect3DVertexDeclaration9_Release(declaration1);
10401 IDirect3DVertexDeclaration9_Release(declaration2);
10402 IDirect3DStateBlock9_Release(stateblock);
10403 refcount = IDirect3DDevice9_Release(device);
10404 ok(!refcount, "Device has %u references left.\n", refcount);
10405 IDirect3D9_Release(d3d);
10406 DestroyWindow(window);
10409 static void test_resource_type(void)
10411 IDirect3DDevice9 *device;
10412 IDirect3DSurface9 *surface;
10413 IDirect3DTexture9 *texture;
10414 IDirect3DCubeTexture9 *cube_texture;
10415 IDirect3DVolume9 *volume;
10416 IDirect3DVolumeTexture9 *volume_texture;
10417 D3DSURFACE_DESC surface_desc;
10418 D3DVOLUME_DESC volume_desc;
10419 D3DRESOURCETYPE type;
10420 IDirect3D9 *d3d;
10421 ULONG refcount;
10422 HWND window;
10423 HRESULT hr;
10424 D3DCAPS9 caps;
10426 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10427 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10428 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10429 ok(!!d3d, "Failed to create a D3D object.\n");
10430 if (!(device = create_device(d3d, window, NULL)))
10432 skip("Failed to create a D3D device, skipping tests.\n");
10433 IDirect3D9_Release(d3d);
10434 DestroyWindow(window);
10435 return;
10438 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10439 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10441 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10442 D3DPOOL_SYSTEMMEM, &surface, NULL);
10443 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10444 type = IDirect3DSurface9_GetType(surface);
10445 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10446 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10447 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10448 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10449 surface_desc.Type);
10450 IDirect3DSurface9_Release(surface);
10452 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10453 D3DPOOL_SYSTEMMEM, &texture, NULL);
10454 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10455 type = IDirect3DTexture9_GetType(texture);
10456 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10458 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10459 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10460 /* The following code crashes, for the sake of completeness:
10461 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10462 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10464 * So applications will not depend on getting the "right" resource type - whatever it
10465 * may be - from the "wrong" vtable. */
10466 type = IDirect3DSurface9_GetType(surface);
10467 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10468 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10469 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10470 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10471 surface_desc.Type);
10472 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10473 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10474 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10475 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10476 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10477 surface_desc.Type);
10478 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10479 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10480 IDirect3DSurface9_Release(surface);
10482 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10483 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10484 type = IDirect3DSurface9_GetType(surface);
10485 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10486 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10487 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10488 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10489 surface_desc.Type);
10490 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10491 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10492 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10493 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10494 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10495 surface_desc.Type);
10496 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10497 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10498 IDirect3DSurface9_Release(surface);
10499 IDirect3DTexture9_Release(texture);
10501 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10503 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10504 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10505 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10506 type = IDirect3DCubeTexture9_GetType(cube_texture);
10507 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10509 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10510 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10511 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10512 type = IDirect3DSurface9_GetType(surface);
10513 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10514 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10515 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10516 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10517 surface_desc.Type);
10518 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10519 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10520 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10521 surface_desc.Type);
10522 IDirect3DSurface9_Release(surface);
10523 IDirect3DCubeTexture9_Release(cube_texture);
10525 else
10526 skip("Cube maps not supported.\n");
10528 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10530 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10531 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10532 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10533 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10534 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10536 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10537 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10538 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10539 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10540 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10541 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10542 volume_desc.Type);
10543 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10544 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10545 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10546 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
10547 ok(SUCCEEDED(hr), "Failed to get level 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 IDirect3DVolume9_Release(volume);
10555 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
10556 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10557 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10558 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10559 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10560 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10561 volume_desc.Type);
10562 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10563 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10564 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10565 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
10566 ok(SUCCEEDED(hr), "Failed to get level 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 IDirect3DVolume9_Release(volume);
10573 IDirect3DVolumeTexture9_Release(volume_texture);
10575 else
10576 skip("Mipmapped volume maps not supported.\n");
10578 refcount = IDirect3DDevice9_Release(device);
10579 ok(!refcount, "Device has %u references left.\n", refcount);
10580 IDirect3D9_Release(d3d);
10581 DestroyWindow(window);
10584 static void test_mipmap_lock(void)
10586 IDirect3DDevice9 *device;
10587 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
10588 IDirect3DTexture9 *texture, *texture_dst;
10589 IDirect3D9 *d3d;
10590 ULONG refcount;
10591 HWND window;
10592 HRESULT hr;
10593 D3DLOCKED_RECT locked_rect;
10595 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10596 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10597 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10598 ok(!!d3d, "Failed to create a D3D object.\n");
10599 if (!(device = create_device(d3d, window, NULL)))
10601 skip("Failed to create a D3D device, skipping tests.\n");
10602 IDirect3D9_Release(d3d);
10603 DestroyWindow(window);
10604 return;
10607 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10608 D3DPOOL_DEFAULT, &texture_dst, NULL);
10609 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10610 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
10611 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10612 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
10613 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10615 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10616 D3DPOOL_SYSTEMMEM, &texture, NULL);
10617 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10618 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10619 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10620 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
10621 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10623 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
10624 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10625 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
10626 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10627 hr = IDirect3DSurface9_UnlockRect(surface);
10628 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10630 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
10631 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
10632 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
10633 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10635 /* Apparently there's no validation on the container. */
10636 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
10637 (IDirect3DBaseTexture9 *)texture_dst);
10638 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
10640 hr = IDirect3DSurface9_UnlockRect(surface2);
10641 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10643 IDirect3DSurface9_Release(surface_dst2);
10644 IDirect3DSurface9_Release(surface_dst);
10645 IDirect3DSurface9_Release(surface2);
10646 IDirect3DSurface9_Release(surface);
10647 IDirect3DTexture9_Release(texture_dst);
10648 IDirect3DTexture9_Release(texture);
10650 refcount = IDirect3DDevice9_Release(device);
10651 ok(!refcount, "Device has %u references left.\n", refcount);
10652 IDirect3D9_Release(d3d);
10653 DestroyWindow(window);
10656 static void test_writeonly_resource(void)
10658 IDirect3D9 *d3d;
10659 IDirect3DDevice9 *device;
10660 IDirect3DVertexBuffer9 *buffer;
10661 ULONG refcount;
10662 HWND window;
10663 HRESULT hr;
10664 void *ptr;
10665 static const struct
10667 struct vec3 pos;
10669 quad[] =
10671 {{-1.0f, -1.0f, 0.0f}},
10672 {{-1.0f, 1.0f, 0.0f}},
10673 {{ 1.0f, -1.0f, 0.0f}},
10674 {{ 1.0f, 1.0f, 0.0f}}
10677 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10678 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10679 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10680 ok(!!d3d, "Failed to create a D3D object.\n");
10681 if (!(device = create_device(d3d, window, NULL)))
10683 skip("Failed to create a D3D device, skipping tests.\n");
10684 IDirect3D9_Release(d3d);
10685 DestroyWindow(window);
10686 return;
10689 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
10690 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
10691 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
10693 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10694 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10695 memcpy(ptr, quad, sizeof(quad));
10696 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10697 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10698 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
10699 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
10700 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10701 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10703 hr = IDirect3DDevice9_BeginScene(device);
10704 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
10705 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
10706 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10707 hr = IDirect3DDevice9_EndScene(device);
10708 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
10710 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
10711 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10712 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10713 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10714 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10716 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
10717 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10718 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10719 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10720 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10722 refcount = IDirect3DVertexBuffer9_Release(buffer);
10723 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
10724 refcount = IDirect3DDevice9_Release(device);
10725 ok(!refcount, "Device has %u references left.\n", refcount);
10726 IDirect3D9_Release(d3d);
10727 DestroyWindow(window);
10730 static void test_lost_device(void)
10732 struct device_desc device_desc;
10733 IDirect3DDevice9 *device;
10734 IDirect3D9 *d3d;
10735 ULONG refcount;
10736 HWND window;
10737 HRESULT hr;
10738 BOOL ret;
10740 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10741 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10742 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10743 ok(!!d3d, "Failed to create a D3D object.\n");
10744 device_desc.device_window = window;
10745 device_desc.width = registry_mode.dmPelsWidth;
10746 device_desc.height = registry_mode.dmPelsHeight;
10747 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10748 if (!(device = create_device(d3d, window, &device_desc)))
10750 skip("Failed to create a D3D device, skipping tests.\n");
10751 goto done;
10754 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10755 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10756 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10757 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10759 ret = SetForegroundWindow(GetDesktopWindow());
10760 ok(ret, "Failed to set foreground window.\n");
10761 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10762 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10763 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10764 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10766 ret = ShowWindow(window, SW_RESTORE);
10767 ok(ret, "Failed to restore window.\n");
10768 ret = SetForegroundWindow(window);
10769 ok(ret, "Failed to set foreground window.\n");
10770 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10771 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
10772 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10773 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10775 hr = reset_device(device, &device_desc);
10776 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10777 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10778 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10779 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10780 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10782 device_desc.flags = 0;
10783 hr = reset_device(device, &device_desc);
10784 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10785 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10786 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10787 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10788 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10790 ret = SetForegroundWindow(GetDesktopWindow());
10791 ok(ret, "Failed to set foreground window.\n");
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 = ShowWindow(window, SW_RESTORE);
10798 ok(ret, "Failed to restore window.\n");
10799 ret = SetForegroundWindow(window);
10800 ok(ret, "Failed to set foreground window.\n");
10801 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10802 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10803 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10804 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10806 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10807 hr = reset_device(device, &device_desc);
10808 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10809 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10810 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10811 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10812 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10814 ret = SetForegroundWindow(GetDesktopWindow());
10815 ok(ret, "Failed to set foreground window.\n");
10816 hr = reset_device(device, &device_desc);
10817 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10818 ret = ShowWindow(window, SW_RESTORE);
10819 ok(ret, "Failed to restore window.\n");
10820 ret = SetForegroundWindow(window);
10821 ok(ret, "Failed to set foreground window.\n");
10822 hr = reset_device(device, &device_desc);
10823 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10825 refcount = IDirect3DDevice9_Release(device);
10826 ok(!refcount, "Device has %u references left.\n", refcount);
10827 done:
10828 IDirect3D9_Release(d3d);
10829 DestroyWindow(window);
10832 static void test_resource_priority(void)
10834 IDirect3DDevice9 *device;
10835 IDirect3DSurface9 *surface;
10836 IDirect3DTexture9 *texture;
10837 IDirect3DVertexBuffer9 *buffer;
10838 IDirect3D9 *d3d;
10839 ULONG refcount;
10840 HWND window;
10841 HRESULT hr;
10842 static const struct
10844 D3DPOOL pool;
10845 const char *name;
10846 BOOL can_set_priority;
10848 test_data[] =
10850 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
10851 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
10852 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
10853 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
10855 unsigned int i;
10856 DWORD priority;
10858 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10859 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10860 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10861 ok(!!d3d, "Failed to create a D3D object.\n");
10862 if (!(device = create_device(d3d, window, NULL)))
10864 skip("Failed to create a D3D device, skipping tests.\n");
10865 IDirect3D9_Release(d3d);
10866 DestroyWindow(window);
10867 return;
10870 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
10872 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
10873 test_data[i].pool, &texture, NULL);
10874 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
10875 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10876 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10878 priority = IDirect3DTexture9_GetPriority(texture);
10879 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10880 priority = IDirect3DTexture9_SetPriority(texture, 1);
10881 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10882 priority = IDirect3DTexture9_GetPriority(texture);
10883 if (test_data[i].can_set_priority)
10885 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10886 priority = IDirect3DTexture9_SetPriority(texture, 2);
10887 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10889 else
10890 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10892 priority = IDirect3DSurface9_GetPriority(surface);
10893 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10894 priority = IDirect3DSurface9_SetPriority(surface, 1);
10895 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10896 priority = IDirect3DSurface9_GetPriority(surface);
10897 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10899 IDirect3DSurface9_Release(surface);
10900 IDirect3DTexture9_Release(texture);
10902 if (test_data[i].pool != D3DPOOL_MANAGED)
10904 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
10905 test_data[i].pool, &surface, NULL);
10906 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
10908 priority = IDirect3DSurface9_GetPriority(surface);
10909 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10910 priority = IDirect3DSurface9_SetPriority(surface, 1);
10911 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10912 priority = IDirect3DSurface9_GetPriority(surface);
10913 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10915 IDirect3DSurface9_Release(surface);
10918 if (test_data[i].pool != D3DPOOL_SCRATCH)
10920 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
10921 test_data[i].pool, &buffer, NULL);
10922 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
10924 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10925 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10926 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
10927 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10928 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10929 if (test_data[i].can_set_priority)
10931 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10932 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
10933 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10935 else
10936 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10938 IDirect3DVertexBuffer9_Release(buffer);
10942 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
10943 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
10945 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
10946 priority = IDirect3DSurface9_GetPriority(surface);
10947 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10948 priority = IDirect3DSurface9_SetPriority(surface, 1);
10949 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10950 priority = IDirect3DSurface9_GetPriority(surface);
10951 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10953 IDirect3DSurface9_Release(surface);
10955 refcount = IDirect3DDevice9_Release(device);
10956 ok(!refcount, "Device has %u references left.\n", refcount);
10957 IDirect3D9_Release(d3d);
10958 DestroyWindow(window);
10961 static void test_swapchain_parameters(void)
10963 IDirect3DDevice9 *device;
10964 IDirect3D9 *d3d;
10965 HWND window;
10966 HRESULT hr;
10967 unsigned int i;
10968 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
10969 IDirect3DSwapChain9 *swapchain;
10970 static const struct
10972 BOOL windowed;
10973 UINT backbuffer_count;
10974 D3DSWAPEFFECT swap_effect;
10975 HRESULT hr;
10977 tests[] =
10979 /* Swap effect 0 is not allowed. */
10980 {TRUE, 1, 0, D3DERR_INVALIDCALL},
10981 {FALSE, 1, 0, D3DERR_INVALIDCALL},
10983 /* All (non-ex) swap effects are allowed in
10984 * windowed and fullscreen mode. */
10985 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10986 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10987 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10988 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10989 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10991 /* Only one backbuffer in copy mode. */
10992 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
10993 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10994 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10995 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10997 /* Ok with the others, in fullscreen and windowed mode. */
10998 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
10999 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11000 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11001 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11003 /* D3D9Ex swap effects. */
11004 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11005 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11006 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11007 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11008 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11009 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11011 /* 3 is the highest allowed backbuffer count. */
11012 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11013 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11014 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11015 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11016 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11019 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11020 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11021 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11022 ok(!!d3d, "Failed to create a D3D object.\n");
11023 if (!(device = create_device(d3d, window, NULL)))
11025 skip("Failed to create a D3D device, skipping tests.\n");
11026 IDirect3D9_Release(d3d);
11027 DestroyWindow(window);
11028 return;
11030 IDirect3DDevice9_Release(device);
11032 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11033 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11034 present_parameters_windowed.hDeviceWindow = window;
11035 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11036 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11037 present_parameters_windowed.Windowed = TRUE;
11038 present_parameters_windowed.BackBufferCount = 1;
11040 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
11042 memset(&present_parameters, 0, sizeof(present_parameters));
11043 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11044 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11045 present_parameters.hDeviceWindow = window;
11046 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11048 present_parameters.SwapEffect = tests[i].swap_effect;
11049 present_parameters.Windowed = tests[i].windowed;
11050 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11052 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11053 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11054 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11055 if (SUCCEEDED(hr))
11057 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11059 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11060 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11062 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11063 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11064 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11065 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11066 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11067 bb_count, present_parameters2.BackBufferCount, i);
11068 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11069 tests[i].windowed, present_parameters2.Windowed, i);
11071 IDirect3DSwapChain9_Release(swapchain);
11072 IDirect3DDevice9_Release(device);
11075 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11076 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11077 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11079 memset(&present_parameters, 0, sizeof(present_parameters));
11080 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11081 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11082 present_parameters.hDeviceWindow = window;
11083 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11085 present_parameters.SwapEffect = tests[i].swap_effect;
11086 present_parameters.Windowed = tests[i].windowed;
11087 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11089 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11090 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11092 if (FAILED(hr))
11094 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11095 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11097 IDirect3DDevice9_Release(device);
11100 IDirect3D9_Release(d3d);
11101 DestroyWindow(window);
11104 static void test_check_device_format(void)
11106 IDirect3D9 *d3d;
11107 HRESULT hr;
11109 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11110 ok(!!d3d, "Failed to create a D3D object.\n");
11112 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11113 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11115 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11117 else
11119 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11120 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11121 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11122 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11123 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11124 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11127 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11128 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11129 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11130 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11131 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11132 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11133 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11134 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11135 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11137 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11138 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, 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 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11142 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11143 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11144 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11145 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11147 IDirect3D9_Release(d3d);
11150 static void test_miptree_layout(void)
11152 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11153 IDirect3DCubeTexture9 *texture_cube;
11154 IDirect3DTexture9 *texture_2d;
11155 IDirect3DDevice9 *device;
11156 D3DLOCKED_RECT map_desc;
11157 BYTE *base = NULL;
11158 IDirect3D9 *d3d;
11159 D3DCAPS9 caps;
11160 UINT refcount;
11161 HWND window;
11162 HRESULT hr;
11164 static const struct
11166 D3DFORMAT format;
11167 const char *name;
11169 formats[] =
11171 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11172 {D3DFMT_A8, "D3DFMT_A8"},
11173 {D3DFMT_L8, "D3DFMT_L8"},
11174 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11175 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11177 static const struct
11179 D3DPOOL pool;
11180 const char *name;
11182 pools[] =
11184 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11185 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11186 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11189 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11190 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11191 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11192 ok(!!d3d, "Failed to create a D3D object.\n");
11193 if (!(device = create_device(d3d, window, NULL)))
11195 skip("Failed to create a D3D device, skipping tests.\n");
11196 goto done;
11199 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11200 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11202 base_dimension = 257;
11203 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11205 skip("Using power of two base dimension.\n");
11206 base_dimension = 256;
11209 for (format_idx = 0; format_idx < sizeof(formats) / sizeof(*formats); ++format_idx)
11211 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11212 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11214 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11215 continue;
11218 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11220 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11221 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11222 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11223 pools[pool_idx].name, formats[format_idx].name, hr);
11225 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11226 for (i = 0, offset = 0; i < level_count; ++i)
11228 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11229 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11230 pools[pool_idx].name, formats[format_idx].name, i, hr);
11232 if (!i)
11233 base = map_desc.pBits;
11234 else
11235 ok(map_desc.pBits == base + offset,
11236 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11237 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11238 offset += (base_dimension >> i) * map_desc.Pitch;
11240 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11241 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11242 pools[pool_idx].name, formats[format_idx].name, i, hr);
11245 IDirect3DTexture9_Release(texture_2d);
11248 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11249 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11251 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11252 continue;
11255 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
11257 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11258 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11259 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11260 pools[pool_idx].name, formats[format_idx].name, hr);
11262 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11263 for (i = 0, offset = 0; i < 6; ++i)
11265 for (j = 0; j < level_count; ++j)
11267 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11268 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11269 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11271 if (!i && !j)
11272 base = map_desc.pBits;
11273 else
11274 ok(map_desc.pBits == base + offset,
11275 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11276 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11277 offset += (base_dimension >> j) * map_desc.Pitch;
11279 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11280 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11281 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11283 offset = (offset + 15) & ~15;
11286 IDirect3DCubeTexture9_Release(texture_cube);
11290 refcount = IDirect3DDevice9_Release(device);
11291 ok(!refcount, "Device has %u references left.\n", refcount);
11292 done:
11293 IDirect3D9_Release(d3d);
11294 DestroyWindow(window);
11297 static void test_get_render_target_data(void)
11299 IDirect3DSurface9 *offscreen_surface, *render_target;
11300 IDirect3DDevice9 *device;
11301 IDirect3D9 *d3d;
11302 UINT refcount;
11303 HWND window;
11304 HRESULT hr;
11306 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11307 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11308 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11309 ok(!!d3d, "Failed to create a D3D object.\n");
11310 if (!(device = create_device(d3d, window, NULL)))
11312 skip("Failed to create a D3D device.\n");
11313 IDirect3D9_Release(d3d);
11314 DestroyWindow(window);
11315 return;
11318 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11319 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11320 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11322 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11323 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11324 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11326 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11327 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11329 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11330 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11332 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11333 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11335 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11336 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11338 IDirect3DSurface9_Release(render_target);
11339 IDirect3DSurface9_Release(offscreen_surface);
11340 refcount = IDirect3DDevice9_Release(device);
11341 ok(!refcount, "Device has %u references left.\n", refcount);
11342 IDirect3D9_Release(d3d);
11343 DestroyWindow(window);
11346 static void test_render_target_device_mismatch(void)
11348 IDirect3DDevice9 *device, *device2;
11349 IDirect3DSurface9 *surface, *rt;
11350 IDirect3D9 *d3d;
11351 UINT refcount;
11352 HWND window;
11353 HRESULT hr;
11355 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11356 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11357 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11358 ok(!!d3d, "Failed to create a D3D object.\n");
11359 if (!(device = create_device(d3d, window, NULL)))
11361 skip("Failed to create a D3D device.\n");
11362 IDirect3D9_Release(d3d);
11363 DestroyWindow(window);
11364 return;
11367 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
11368 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11370 device2 = create_device(d3d, window, NULL);
11371 ok(!!device2, "Failed to create a D3D device.\n");
11373 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11374 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11375 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11377 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11378 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11380 IDirect3DSurface9_Release(surface);
11382 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11383 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11385 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11386 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11388 IDirect3DSurface9_Release(surface);
11390 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11391 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11392 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11393 IDirect3DSurface9_Release(surface);
11394 IDirect3DSurface9_Release(rt);
11396 refcount = IDirect3DDevice9_Release(device);
11397 ok(!refcount, "Device has %u references left.\n", refcount);
11398 refcount = IDirect3DDevice9_Release(device2);
11399 ok(!refcount, "Device has %u references left.\n", refcount);
11400 IDirect3D9_Release(d3d);
11401 DestroyWindow(window);
11404 START_TEST(device)
11406 WNDCLASSA wc = {0};
11407 IDirect3D9 *d3d9;
11408 DEVMODEW current_mode;
11410 memset(&current_mode, 0, sizeof(current_mode));
11411 current_mode.dmSize = sizeof(current_mode);
11412 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
11413 registry_mode.dmSize = sizeof(registry_mode);
11414 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
11415 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
11416 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
11418 skip("Current mode does not match registry mode, skipping test.\n");
11419 return;
11422 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
11424 skip("could not create D3D9 object\n");
11425 return;
11427 IDirect3D9_Release(d3d9);
11429 wc.lpfnWndProc = DefWindowProcA;
11430 wc.lpszClassName = "d3d9_test_wc";
11431 RegisterClassA(&wc);
11433 test_get_set_vertex_declaration();
11434 test_get_declaration();
11435 test_fvf_decl_conversion();
11436 test_fvf_decl_management();
11437 test_vertex_declaration_alignment();
11438 test_unused_declaration_type();
11439 test_fpu_setup();
11440 test_multi_device();
11441 test_display_formats();
11442 test_display_modes();
11443 test_swapchain();
11444 test_refcount();
11445 test_mipmap_levels();
11446 test_checkdevicemultisampletype();
11447 test_invalid_multisample();
11448 test_cursor();
11449 test_cursor_pos();
11450 test_reset_fullscreen();
11451 test_reset();
11452 test_scene();
11453 test_limits();
11454 test_depthstenciltest();
11455 test_get_rt();
11456 test_draw_primitive();
11457 test_null_stream();
11458 test_lights();
11459 test_set_stream_source();
11460 test_scissor_size();
11461 test_wndproc();
11462 test_wndproc_windowed();
11463 test_window_style();
11464 test_mode_change();
11465 test_device_window_reset();
11466 test_reset_resources();
11467 test_set_rt_vp_scissor();
11468 test_volume_get_container();
11469 test_volume_resource();
11470 test_vb_lock_flags();
11471 test_vertex_buffer_alignment();
11472 test_query_support();
11473 test_occlusion_query();
11474 test_timestamp_query();
11475 test_get_set_vertex_shader();
11476 test_vertex_shader_constant();
11477 test_get_set_pixel_shader();
11478 test_pixel_shader_constant();
11479 test_unsupported_shaders();
11480 test_texture_stage_states();
11481 test_cube_textures();
11482 test_mipmap_gen();
11483 test_filter();
11484 test_get_set_texture();
11485 test_lod();
11486 test_surface_get_container();
11487 test_surface_alignment();
11488 test_lockrect_offset();
11489 test_lockrect_invalid();
11490 test_private_data();
11491 test_getdc();
11492 test_surface_dimensions();
11493 test_surface_format_null();
11494 test_surface_double_unlock();
11495 test_surface_blocks();
11496 test_set_palette();
11497 test_swvp_buffer();
11498 test_managed_buffer();
11499 test_npot_textures();
11500 test_vidmem_accounting();
11501 test_volume_locking();
11502 test_update_volumetexture();
11503 test_create_rt_ds_fail();
11504 test_volume_blocks();
11505 test_lockbox_invalid();
11506 test_shared_handle();
11507 test_pixel_format();
11508 test_begin_end_state_block();
11509 test_shader_constant_apply();
11510 test_vdecl_apply();
11511 test_resource_type();
11512 test_mipmap_lock();
11513 test_writeonly_resource();
11514 test_lost_device();
11515 test_resource_priority();
11516 test_swapchain_parameters();
11517 test_check_device_format();
11518 test_miptree_layout();
11519 test_get_render_target_data();
11520 test_render_target_device_mismatch();
11522 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));