d3d9/tests: Properly check for mipmap autogeneration support.
[wine.git] / dlls / d3d9 / tests / device.c
blobcb737e226cb727fd2acb7877f22385c7212bb44f
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 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
32 struct vec3
34 float x, y, z;
37 #define CREATE_DEVICE_FULLSCREEN 0x01
38 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
39 #define CREATE_DEVICE_FPU_PRESERVE 0x04
40 #define CREATE_DEVICE_SWVP_ONLY 0x08
41 #define CREATE_DEVICE_MIXED_ONLY 0x10
42 #define CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT 0x20
43 #define CREATE_DEVICE_LOCKABLE_BACKBUFFER 0x40
45 struct device_desc
47 HWND device_window;
48 unsigned int width;
49 unsigned int height;
50 DWORD flags;
53 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
54 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
56 static DEVMODEW registry_mode;
58 static const DWORD simple_vs[] =
60 0xfffe0101, /* vs_1_1 */
61 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
62 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
63 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
64 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
65 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
66 0x0000ffff, /* end */
69 static const DWORD simple_ps[] =
71 0xffff0101, /* ps_1_1 */
72 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
73 0x00000042, 0xb00f0000, /* tex t0 */
74 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
75 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
76 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
77 0x0000ffff, /* end */
80 static int get_refcount(IUnknown *object)
82 IUnknown_AddRef( object );
83 return IUnknown_Release( object );
86 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
88 unsigned int element_count, i;
89 D3DVERTEXELEMENT9 *elements;
90 BOOL equal = TRUE;
91 HRESULT hr;
93 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
94 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
95 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
96 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
97 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
99 for (i = 0; i < element_count; ++i)
101 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
103 equal = FALSE;
104 break;
108 if (!equal)
110 for (i = 0; i < element_count; ++i)
112 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
113 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
114 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
118 HeapFree(GetProcessHeap(), 0, elements);
119 return equal;
122 /* try to make sure pending X events have been processed before continuing */
123 static void flush_events(void)
125 MSG msg;
126 int diff = 200;
127 int min_timeout = 100;
128 DWORD time = GetTickCount() + diff;
130 while (diff > 0)
132 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
133 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
134 diff = time - GetTickCount();
138 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
140 D3DPRESENT_PARAMETERS present_parameters = {0};
141 IDirect3DDevice9 *device;
142 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
144 present_parameters.BackBufferWidth = 640;
145 present_parameters.BackBufferHeight = 480;
146 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
147 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
148 present_parameters.hDeviceWindow = focus_window;
149 present_parameters.Windowed = TRUE;
150 present_parameters.EnableAutoDepthStencil = TRUE;
151 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
153 if (desc)
155 present_parameters.BackBufferWidth = desc->width;
156 present_parameters.BackBufferHeight = desc->height;
157 if (desc->flags & CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT)
158 present_parameters.BackBufferFormat = D3DFMT_UNKNOWN;
159 present_parameters.hDeviceWindow = desc->device_window;
160 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
161 if (desc->flags & CREATE_DEVICE_LOCKABLE_BACKBUFFER)
162 present_parameters.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
163 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
164 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
165 else if (desc->flags & CREATE_DEVICE_MIXED_ONLY)
166 behavior_flags = D3DCREATE_MIXED_VERTEXPROCESSING;
167 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
168 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
169 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
170 behavior_flags |= D3DCREATE_FPU_PRESERVE;
173 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
174 behavior_flags, &present_parameters, &device)))
175 return device;
177 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
178 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
179 behavior_flags, &present_parameters, &device)))
180 return device;
182 if (desc && (desc->flags & (CREATE_DEVICE_SWVP_ONLY | CREATE_DEVICE_MIXED_ONLY)))
183 return NULL;
184 behavior_flags = (behavior_flags
185 & ~(D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING))
186 | D3DCREATE_HARDWARE_VERTEXPROCESSING;
188 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
189 behavior_flags, &present_parameters, &device)))
190 return device;
192 return NULL;
195 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
197 D3DPRESENT_PARAMETERS present_parameters = {0};
199 present_parameters.BackBufferWidth = 640;
200 present_parameters.BackBufferHeight = 480;
201 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
202 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
203 present_parameters.hDeviceWindow = NULL;
204 present_parameters.Windowed = TRUE;
205 present_parameters.EnableAutoDepthStencil = TRUE;
206 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
208 if (desc)
210 present_parameters.BackBufferWidth = desc->width;
211 present_parameters.BackBufferHeight = desc->height;
212 present_parameters.hDeviceWindow = desc->device_window;
213 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
216 return IDirect3DDevice9_Reset(device, &present_parameters);
219 #define CHECK_CALL(r,c,d,rc) \
220 if (SUCCEEDED(r)) {\
221 int tmp1 = get_refcount( (IUnknown *)d ); \
222 int rc_new = rc; \
223 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
224 } else {\
225 trace("%s failed: %08x\n", c, r); \
228 #define CHECK_RELEASE(obj,d,rc) \
229 if (obj) { \
230 int tmp1, rc_new = rc; \
231 IUnknown_Release( (IUnknown*)obj ); \
232 tmp1 = get_refcount( (IUnknown *)d ); \
233 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
236 #define CHECK_REFCOUNT(obj,rc) \
238 int rc_new = rc; \
239 int count = get_refcount( (IUnknown *)obj ); \
240 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
243 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
245 int rc_new = rc; \
246 int count = IUnknown_Release( (IUnknown *)obj ); \
247 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
250 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
252 int rc_new = rc; \
253 int count = IUnknown_AddRef( (IUnknown *)obj ); \
254 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
257 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
259 void *container_ptr = (void *)0x1337c0d3; \
260 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
261 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
262 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
263 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
266 static void test_get_set_vertex_declaration(void)
268 IDirect3DVertexDeclaration9 *declaration, *tmp;
269 ULONG refcount, expected_refcount;
270 IDirect3DDevice9 *device;
271 IDirect3D9 *d3d;
272 HWND window;
273 HRESULT hr;
275 static const D3DVERTEXELEMENT9 simple_decl[] =
277 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
278 D3DDECL_END()
281 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
282 0, 0, 640, 480, NULL, NULL, NULL, NULL);
283 d3d = Direct3DCreate9(D3D_SDK_VERSION);
284 ok(!!d3d, "Failed to create a D3D object.\n");
285 if (!(device = create_device(d3d, window, NULL)))
287 skip("Failed to create a D3D device, skipping tests.\n");
288 goto done;
291 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
292 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
294 /* SetVertexDeclaration() should not touch the declaration's refcount. */
295 expected_refcount = get_refcount((IUnknown *)declaration);
296 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
297 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
298 refcount = get_refcount((IUnknown *)declaration);
299 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
301 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
302 tmp = NULL;
303 expected_refcount = refcount + 1;
304 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
305 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
306 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
307 refcount = get_refcount((IUnknown *)declaration);
308 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
309 IDirect3DVertexDeclaration9_Release(tmp);
311 IDirect3DVertexDeclaration9_Release(declaration);
312 refcount = IDirect3DDevice9_Release(device);
313 ok(!refcount, "Device has %u references left.\n", refcount);
314 done:
315 IDirect3D9_Release(d3d);
316 DestroyWindow(window);
319 static void test_get_declaration(void)
321 unsigned int element_count, expected_element_count;
322 IDirect3DVertexDeclaration9 *declaration;
323 D3DVERTEXELEMENT9 *elements;
324 IDirect3DDevice9 *device;
325 IDirect3D9 *d3d;
326 ULONG refcount;
327 HWND window;
328 HRESULT hr;
330 static const D3DVERTEXELEMENT9 simple_decl[] =
332 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
333 D3DDECL_END()
336 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
337 0, 0, 640, 480, NULL, NULL, NULL, NULL);
338 d3d = Direct3DCreate9(D3D_SDK_VERSION);
339 ok(!!d3d, "Failed to create a D3D object.\n");
340 if (!(device = create_device(d3d, window, NULL)))
342 skip("Failed to create a D3D device, skipping tests.\n");
343 goto done;
346 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
347 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
349 /* First test only getting the number of elements. */
350 element_count = 0x1337c0de;
351 expected_element_count = ARRAY_SIZE(simple_decl);
352 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
353 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
354 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
355 element_count, expected_element_count);
357 element_count = 0;
358 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
359 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
360 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
361 element_count, expected_element_count);
363 /* Also test the returned data. */
364 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
366 element_count = 0x1337c0de;
367 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
368 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
369 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
370 element_count, expected_element_count);
371 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
372 "Original and returned vertexdeclarations are not the same.\n");
374 memset(elements, 0, sizeof(simple_decl));
376 element_count = 0;
377 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
378 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
379 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
380 element_count, expected_element_count);
381 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
382 "Original and returned vertexdeclarations are not the same.\n");
384 HeapFree(GetProcessHeap(), 0, elements);
385 IDirect3DVertexDeclaration9_Release(declaration);
386 refcount = IDirect3DDevice9_Release(device);
387 ok(!refcount, "Device has %u references left.\n", refcount);
388 done:
389 IDirect3D9_Release(d3d);
390 DestroyWindow(window);
393 static void test_fvf_decl_conversion(void)
395 IDirect3DVertexDeclaration9 *default_decl;
396 IDirect3DVertexDeclaration9 *declaration;
397 IDirect3DDevice9 *device;
398 IDirect3D9 *d3d;
399 ULONG refcount;
400 unsigned int i;
401 HWND window;
402 HRESULT hr;
404 static const D3DVERTEXELEMENT9 default_elements[] =
406 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
407 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
408 D3DDECL_END()
410 /* Test conversions from vertex declaration to an FVF. For some reason
411 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
412 * forced to 0 - maybe this is configuration specific. */
413 static const struct
415 D3DVERTEXELEMENT9 elements[7];
416 DWORD fvf;
417 BOOL todo;
419 decl_to_fvf_tests[] =
421 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
422 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
423 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
424 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
425 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
426 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
427 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
428 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
429 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
430 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
431 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
432 /* No FVF mapping available. */
433 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
434 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
435 /* Try empty declaration. */
436 {{ D3DDECL_END()}, 0, FALSE},
437 /* Make sure textures of different sizes work. */
438 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
439 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
440 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
441 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
442 /* Make sure the TEXCOORD index works correctly - try several textures. */
445 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
446 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
447 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
448 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
449 D3DDECL_END(),
450 }, 0, FALSE,
452 /* Now try a combination test. */
455 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
456 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
457 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
458 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
459 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
460 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
461 D3DDECL_END(),
462 }, 0, FALSE,
465 /* Test conversions from FVF to a vertex declaration. These seem to always
466 * occur internally. A new declaration object is created if necessary. */
467 static const struct
469 DWORD fvf;
470 D3DVERTEXELEMENT9 elements[7];
472 fvf_to_decl_tests[] =
474 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
475 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
476 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
478 D3DFVF_XYZB5,
480 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
481 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
482 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
483 D3DDECL_END(),
487 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
489 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
490 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
491 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
492 D3DDECL_END(),
496 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
498 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
499 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
500 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
501 D3DDECL_END(),
505 D3DFVF_XYZB1,
507 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
508 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
509 D3DDECL_END(),
513 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
515 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
516 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
517 D3DDECL_END(),
521 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
523 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
524 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
525 D3DDECL_END(),
529 D3DFVF_XYZB2,
531 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
532 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
533 D3DDECL_END(),
537 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
539 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
540 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
541 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
542 D3DDECL_END(),
546 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
548 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
549 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
550 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
551 D3DDECL_END(),
555 D3DFVF_XYZB3,
557 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
558 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
559 D3DDECL_END(),
563 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
565 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
566 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
567 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
568 D3DDECL_END(),
572 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
574 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
575 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
576 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
577 D3DDECL_END(),
581 D3DFVF_XYZB4,
583 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
584 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
585 D3DDECL_END(),
589 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
591 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
592 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
593 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
594 D3DDECL_END(),
598 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
600 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
601 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
602 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
603 D3DDECL_END(),
606 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
607 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
608 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
609 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
610 /* Make sure textures of different sizes work. */
612 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
613 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
616 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
617 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
620 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
621 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
624 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
625 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
627 /* Make sure the TEXCOORD index works correctly - try several textures. */
629 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
630 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
632 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
633 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
634 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
635 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
636 D3DDECL_END(),
639 /* Now try a combination test. */
641 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
642 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
644 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
645 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
646 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
647 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
648 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
649 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
650 D3DDECL_END(),
655 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
656 0, 0, 640, 480, NULL, NULL, NULL, NULL);
657 d3d = Direct3DCreate9(D3D_SDK_VERSION);
658 ok(!!d3d, "Failed to create a D3D object.\n");
659 if (!(device = create_device(d3d, window, NULL)))
661 skip("Failed to create a D3D device, skipping tests.\n");
662 goto done;
665 for (i = 0; i < ARRAY_SIZE(decl_to_fvf_tests); ++i)
667 DWORD fvf = 0xdeadbeef;
668 HRESULT hr;
670 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
671 * back to 0. */
672 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
673 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
675 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
676 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
677 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
678 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
680 /* Check the FVF. */
681 hr = IDirect3DDevice9_GetFVF(device, &fvf);
682 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
684 todo_wine_if (decl_to_fvf_tests[i].todo)
685 ok(fvf == decl_to_fvf_tests[i].fvf,
686 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
687 i, fvf, decl_to_fvf_tests[i].fvf);
689 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
690 IDirect3DVertexDeclaration9_Release(declaration);
693 /* Create a default declaration and FVF that does not match any of the
694 * tests. */
695 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
696 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
698 for (i = 0; i < ARRAY_SIZE(fvf_to_decl_tests); ++i)
700 /* Set a default declaration to make sure it is changed. */
701 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
702 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
704 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
705 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
707 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
708 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
709 ok(!!declaration && declaration != default_decl,
710 "Test %u: Got unexpected declaration %p.\n", i, declaration);
711 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
712 "Test %u: Declaration does not match.\n", i);
713 IDirect3DVertexDeclaration9_Release(declaration);
716 /* Setting the FVF to 0 should result in no change to the default decl. */
717 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
718 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
719 hr = IDirect3DDevice9_SetFVF(device, 0);
720 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
721 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
722 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
723 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
724 IDirect3DVertexDeclaration9_Release(declaration);
726 IDirect3DVertexDeclaration9_Release(default_decl);
727 refcount = IDirect3DDevice9_Release(device);
728 ok(!refcount, "Device has %u references left.\n", refcount);
729 done:
730 IDirect3D9_Release(d3d);
731 DestroyWindow(window);
734 /* Check whether a declaration converted from FVF is shared.
735 * Check whether refcounts behave as expected. */
736 static void test_fvf_decl_management(void)
738 IDirect3DVertexDeclaration9 *declaration1;
739 IDirect3DVertexDeclaration9 *declaration2;
740 IDirect3DVertexDeclaration9 *declaration3;
741 IDirect3DVertexDeclaration9 *declaration4;
742 IDirect3DDevice9 *device;
743 IDirect3D9 *d3d;
744 ULONG refcount;
745 HWND window;
746 HRESULT hr;
748 static const D3DVERTEXELEMENT9 test_elements1[] =
749 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
750 static const D3DVERTEXELEMENT9 test_elements2[] =
751 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
753 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
754 0, 0, 640, 480, NULL, NULL, NULL, NULL);
755 d3d = Direct3DCreate9(D3D_SDK_VERSION);
756 ok(!!d3d, "Failed to create a D3D object.\n");
757 if (!(device = create_device(d3d, window, NULL)))
759 skip("Failed to create a D3D device, skipping tests.\n");
760 goto done;
763 /* Clear down any current vertex declaration. */
764 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
765 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
766 /* Conversion. */
767 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
768 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
769 /* Get converted decl (#1). */
770 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
771 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
772 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
773 /* Get converted decl again (#2). */
774 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
775 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
776 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
778 /* Conversion. */
779 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
780 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
781 /* Get converted decl (#3). */
782 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
783 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
784 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
785 /* The contents should correspond to the second conversion. */
786 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
787 /* Re-Check if the first decl was overwritten by the new Get(). */
788 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
790 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
791 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
792 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
793 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
794 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
796 refcount = get_refcount((IUnknown*)declaration1);
797 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
798 refcount = get_refcount((IUnknown*)declaration2);
799 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
800 refcount = get_refcount((IUnknown*)declaration3);
801 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
802 refcount = get_refcount((IUnknown*)declaration4);
803 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
805 IDirect3DVertexDeclaration9_Release(declaration4);
806 IDirect3DVertexDeclaration9_Release(declaration3);
807 IDirect3DVertexDeclaration9_Release(declaration2);
808 IDirect3DVertexDeclaration9_Release(declaration1);
810 refcount = IDirect3DDevice9_Release(device);
811 ok(!refcount, "Device has %u references left.\n", refcount);
812 done:
813 IDirect3D9_Release(d3d);
814 DestroyWindow(window);
817 static void test_vertex_declaration_alignment(void)
819 IDirect3DVertexDeclaration9 *declaration;
820 IDirect3DDevice9 *device;
821 IDirect3D9 *d3d;
822 unsigned int i;
823 ULONG refcount;
824 HWND window;
825 HRESULT hr;
827 static const struct
829 D3DVERTEXELEMENT9 elements[3];
830 HRESULT hr;
832 test_data[] =
836 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
837 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
838 D3DDECL_END(),
839 }, D3D_OK,
843 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
844 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
845 D3DDECL_END(),
846 }, E_FAIL,
850 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
851 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
852 D3DDECL_END(),
853 }, E_FAIL,
857 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
858 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
859 D3DDECL_END(),
860 }, E_FAIL,
864 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
865 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
866 D3DDECL_END(),
867 }, D3D_OK,
871 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
872 0, 0, 640, 480, NULL, NULL, NULL, NULL);
873 d3d = Direct3DCreate9(D3D_SDK_VERSION);
874 ok(!!d3d, "Failed to create a D3D object.\n");
875 if (!(device = create_device(d3d, window, NULL)))
877 skip("Failed to create a D3D device, skipping tests.\n");
878 goto done;
881 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
883 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
884 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
885 if (SUCCEEDED(hr))
886 IDirect3DVertexDeclaration9_Release(declaration);
889 refcount = IDirect3DDevice9_Release(device);
890 ok(!refcount, "Device has %u references left.\n", refcount);
891 done:
892 IDirect3D9_Release(d3d);
893 DestroyWindow(window);
896 static void test_unused_declaration_type(void)
898 IDirect3DVertexDeclaration9 *declaration;
899 IDirect3DDevice9 *device;
900 IDirect3D9 *d3d;
901 unsigned int i;
902 ULONG refcount;
903 HWND window;
904 HRESULT hr;
906 static const D3DVERTEXELEMENT9 test_elements[][3] =
909 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
910 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
911 D3DDECL_END(),
914 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
915 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
916 D3DDECL_END(),
919 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
920 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
921 D3DDECL_END(),
924 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
925 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
926 D3DDECL_END(),
929 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
930 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
931 D3DDECL_END(),
934 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
935 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
936 D3DDECL_END(),
939 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
940 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
941 D3DDECL_END(),
945 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
946 0, 0, 640, 480, NULL, NULL, NULL, NULL);
947 d3d = Direct3DCreate9(D3D_SDK_VERSION);
948 ok(!!d3d, "Failed to create a D3D object.\n");
949 if (!(device = create_device(d3d, window, NULL)))
951 skip("Failed to create a D3D device, skipping tests.\n");
952 goto done;
955 for (i = 0; i < ARRAY_SIZE(test_elements); ++i)
957 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
958 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
961 refcount = IDirect3DDevice9_Release(device);
962 ok(!refcount, "Device has %u references left.\n", refcount);
963 done:
964 IDirect3D9_Release(d3d);
965 DestroyWindow(window);
968 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
970 IDirect3DBaseTexture9* texture = NULL;
971 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
972 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
974 if (SUCCEEDED(hr)) {
975 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
976 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
977 } else
978 trace("CreateTexture failed: %08x\n", hr);
980 if (texture) IDirect3DBaseTexture9_Release( texture );
983 static void test_mipmap_levels(void)
985 IDirect3DDevice9 *device;
986 IDirect3D9 *d3d;
987 ULONG refcount;
988 HWND window;
990 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
991 0, 0, 640, 480, NULL, NULL, NULL, NULL);
992 ok(!!window, "Failed to create a window.\n");
993 d3d = Direct3DCreate9(D3D_SDK_VERSION);
994 ok(!!d3d, "Failed to create a D3D object.\n");
995 if (!(device = create_device(d3d, window, NULL)))
997 skip("Failed to create a 3D device, skipping test.\n");
998 goto cleanup;
1001 check_mipmap_levels(device, 32, 32, 6);
1002 check_mipmap_levels(device, 256, 1, 9);
1003 check_mipmap_levels(device, 1, 256, 9);
1004 check_mipmap_levels(device, 1, 1, 1);
1006 refcount = IDirect3DDevice9_Release(device);
1007 ok(!refcount, "Device has %u references left.\n", refcount);
1008 cleanup:
1009 IDirect3D9_Release(d3d);
1010 DestroyWindow(window);
1013 static void test_checkdevicemultisampletype(void)
1015 DWORD quality_levels;
1016 IDirect3D9 *d3d;
1017 HWND window;
1018 HRESULT hr;
1020 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1021 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1022 ok(!!window, "Failed to create a window.\n");
1023 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1024 ok(!!d3d, "Failed to create a D3D object.\n");
1026 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1027 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL) == D3DERR_NOTAVAILABLE)
1029 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
1030 goto cleanup;
1033 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1034 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE, NULL);
1035 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1036 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1037 65536, TRUE, D3DMULTISAMPLE_NONE, NULL);
1038 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1040 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1041 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, NULL);
1042 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1044 quality_levels = 0;
1045 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1046 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1047 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1048 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1049 quality_levels = 0;
1050 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1051 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1052 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1053 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1055 quality_levels = 0;
1056 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1057 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, NULL);
1058 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1059 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1060 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels);
1061 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1062 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1064 quality_levels = 0;
1065 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1066 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1067 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1068 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1069 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels);
1070 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1071 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1073 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1074 quality_levels = 0;
1075 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1076 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1077 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1078 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1079 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, &quality_levels);
1080 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1081 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1083 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1084 D3DFMT_X8R8G8B8, TRUE, 65536, NULL);
1085 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1087 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1088 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1089 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1091 cleanup:
1092 IDirect3D9_Release(d3d);
1093 DestroyWindow(window);
1096 static void test_invalid_multisample(void)
1098 IDirect3DDevice9 *device;
1099 IDirect3DSurface9 *rt;
1100 DWORD quality_levels;
1101 IDirect3D9 *d3d;
1102 BOOL available;
1103 ULONG refcount;
1104 HWND window;
1105 HRESULT hr;
1107 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1108 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1109 ok(!!window, "Failed to create a window.\n");
1110 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1111 ok(!!d3d, "Failed to create a D3D object.\n");
1113 if (!(device = create_device(d3d, window, NULL)))
1115 skip("Failed to create a 3D device, skipping test.\n");
1116 goto cleanup;
1119 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1120 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels));
1121 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1122 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, 0, FALSE, &rt, NULL);
1123 if (available)
1125 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1126 IDirect3DSurface9_Release(rt);
1127 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1128 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, quality_levels, FALSE, &rt, NULL);
1129 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1131 else
1133 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1136 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1137 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels));
1138 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1139 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &rt, NULL);
1140 if (available)
1142 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1143 IDirect3DSurface9_Release(rt);
1144 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1145 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels, FALSE, &rt, NULL);
1146 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1148 else
1150 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1153 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1154 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1155 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1156 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1157 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1158 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, 0, FALSE, &rt, NULL);
1159 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1161 refcount = IDirect3DDevice9_Release(device);
1162 ok(!refcount, "Device has %u references left.\n", refcount);
1163 cleanup:
1164 IDirect3D9_Release(d3d);
1165 DestroyWindow(window);
1168 static void test_swapchain(void)
1170 IDirect3DSwapChain9 *swapchain0;
1171 IDirect3DSwapChain9 *swapchain1;
1172 IDirect3DSwapChain9 *swapchain2;
1173 IDirect3DSwapChain9 *swapchain3;
1174 IDirect3DSwapChain9 *swapchainX;
1175 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1176 D3DPRESENT_PARAMETERS d3dpp;
1177 IDirect3DDevice9 *device;
1178 IDirect3D9 *d3d;
1179 ULONG refcount;
1180 HWND window, window2;
1181 HRESULT hr;
1182 struct device_desc device_desc;
1184 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1185 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1186 ok(!!window, "Failed to create a window.\n");
1187 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1188 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1189 ok(!!window2, "Failed to create a window.\n");
1190 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1191 ok(!!d3d, "Failed to create a D3D object.\n");
1192 if (!(device = create_device(d3d, window, NULL)))
1194 skip("Failed to create a 3D device, skipping test.\n");
1195 goto cleanup;
1198 /* Get the implicit swapchain */
1199 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1200 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1201 /* Check if the back buffer count was modified */
1202 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1203 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1204 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1205 IDirect3DSwapChain9_Release(swapchain0);
1207 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1208 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1209 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1210 backbuffer = (void *)0xdeadbeef;
1211 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1212 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1213 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1214 backbuffer = (void *)0xdeadbeef;
1215 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1216 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1217 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1219 /* Check if there is a back buffer */
1220 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1221 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1222 ok(backbuffer != NULL, "The back buffer is NULL\n");
1223 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1225 /* The back buffer type value is ignored. */
1226 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 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 = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 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 = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 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 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1240 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1241 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1242 IDirect3DSurface9_Release(stereo_buffer);
1243 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1244 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1245 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1246 IDirect3DSurface9_Release(stereo_buffer);
1247 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1248 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1249 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1250 IDirect3DSurface9_Release(stereo_buffer);
1252 /* Try to get a nonexistent swapchain */
1253 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1254 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1255 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1256 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1258 /* Create a bunch of swapchains */
1259 d3dpp.BackBufferCount = 0;
1260 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1261 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1262 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1264 d3dpp.BackBufferCount = 1;
1265 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1266 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1268 d3dpp.BackBufferCount = 2;
1269 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1270 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1271 if(SUCCEEDED(hr)) {
1272 /* Swapchain 3, created with backbuffercount 2 */
1273 backbuffer = (void *) 0xdeadbeef;
1274 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1275 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1276 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1277 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1279 backbuffer = (void *) 0xdeadbeef;
1280 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1281 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1282 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1283 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1285 backbuffer = (void *) 0xdeadbeef;
1286 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1287 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1288 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1289 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1291 backbuffer = (void *) 0xdeadbeef;
1292 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1293 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1294 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1295 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1298 /* Check the back buffers of the swapchains */
1299 /* Swapchain 1, created with backbuffercount 0 */
1300 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1301 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1302 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1303 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1305 backbuffer = (void *) 0xdeadbeef;
1306 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1307 ok(FAILED(hr), "Failed to get the back buffer (%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 /* Swapchain 2 - created with backbuffercount 1 */
1312 backbuffer = (void *) 0xdeadbeef;
1313 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1314 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1315 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1316 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1318 backbuffer = (void *) 0xdeadbeef;
1319 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1320 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1321 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1322 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1324 backbuffer = (void *) 0xdeadbeef;
1325 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1326 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1327 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1328 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1330 /* Try getSwapChain on a manually created swapchain
1331 * it should fail, apparently GetSwapChain only returns implicit swapchains
1333 swapchainX = (void *) 0xdeadbeef;
1334 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1335 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1336 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1337 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1339 IDirect3DSwapChain9_Release(swapchain3);
1340 IDirect3DSwapChain9_Release(swapchain2);
1341 IDirect3DSwapChain9_Release(swapchain1);
1343 d3dpp.Windowed = FALSE;
1344 d3dpp.hDeviceWindow = window;
1345 d3dpp.BackBufferCount = 1;
1346 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1347 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1348 d3dpp.hDeviceWindow = window2;
1349 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1350 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1352 device_desc.width = registry_mode.dmPelsWidth;
1353 device_desc.height = registry_mode.dmPelsHeight;
1354 device_desc.device_window = window;
1355 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1356 hr = reset_device(device, &device_desc);
1357 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1359 d3dpp.hDeviceWindow = window;
1360 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1361 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1362 d3dpp.hDeviceWindow = window2;
1363 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1364 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1365 d3dpp.Windowed = TRUE;
1366 d3dpp.hDeviceWindow = window;
1367 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1368 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1369 d3dpp.hDeviceWindow = window2;
1370 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1371 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1373 refcount = IDirect3DDevice9_Release(device);
1374 ok(!refcount, "Device has %u references left.\n", refcount);
1375 cleanup:
1376 IDirect3D9_Release(d3d);
1377 DestroyWindow(window2);
1378 DestroyWindow(window);
1381 static void test_refcount(void)
1383 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1384 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1385 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1386 IDirect3DVertexShader9 *pVertexShader = NULL;
1387 IDirect3DPixelShader9 *pPixelShader = NULL;
1388 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1389 IDirect3DTexture9 *pTexture = NULL;
1390 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1391 IDirect3DVolume9 *pVolumeLevel = NULL;
1392 IDirect3DSurface9 *pStencilSurface = NULL;
1393 IDirect3DSurface9 *pOffscreenSurface = NULL;
1394 IDirect3DSurface9 *pRenderTarget = NULL;
1395 IDirect3DSurface9 *pRenderTarget2 = NULL;
1396 IDirect3DSurface9 *pRenderTarget3 = NULL;
1397 IDirect3DSurface9 *pTextureLevel = NULL;
1398 IDirect3DSurface9 *pBackBuffer = NULL;
1399 IDirect3DStateBlock9 *pStateBlock = NULL;
1400 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1401 IDirect3DSwapChain9 *pSwapChain = NULL;
1402 IDirect3DQuery9 *pQuery = NULL;
1403 D3DPRESENT_PARAMETERS d3dpp;
1404 IDirect3DDevice9 *device;
1405 ULONG refcount = 0, tmp;
1406 IDirect3D9 *d3d, *d3d2;
1407 HWND window;
1408 HRESULT hr;
1410 D3DVERTEXELEMENT9 decl[] =
1412 D3DDECL_END()
1415 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1416 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1417 ok(!!window, "Failed to create a window.\n");
1418 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1419 ok(!!d3d, "Failed to create a D3D object.\n");
1421 CHECK_REFCOUNT(d3d, 1);
1423 if (!(device = create_device(d3d, window, NULL)))
1425 skip("Failed to create a 3D device, skipping test.\n");
1426 goto cleanup;
1429 refcount = get_refcount((IUnknown *)device);
1430 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1432 CHECK_REFCOUNT(d3d, 2);
1434 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1435 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1437 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1438 CHECK_REFCOUNT(d3d, 3);
1439 CHECK_RELEASE_REFCOUNT(d3d, 2);
1442 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1443 * - the container is the device OR swapchain
1444 * - they hold a reference to the device
1445 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1446 * - they are not freed if refcount reaches 0.
1447 * - the refcount is not forwarded to the container.
1449 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1450 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1451 if (pSwapChain)
1453 CHECK_REFCOUNT(pSwapChain, 1);
1455 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1456 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1457 CHECK_REFCOUNT(pSwapChain, 1);
1458 if (pRenderTarget)
1460 CHECK_SURFACE_CONTAINER(pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1461 CHECK_REFCOUNT(pRenderTarget, 1);
1463 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1464 CHECK_REFCOUNT(device, refcount);
1465 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1466 CHECK_REFCOUNT(device, refcount);
1468 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1469 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1470 CHECK_REFCOUNT(pRenderTarget, 2);
1471 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1472 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1473 CHECK_REFCOUNT(device, --refcount);
1475 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1476 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1477 CHECK_REFCOUNT(device, ++refcount);
1478 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1479 CHECK_REFCOUNT(device, --refcount);
1480 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1481 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1484 /* Render target and back buffer are identical. */
1485 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1486 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1487 if (pBackBuffer)
1489 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1490 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1491 pRenderTarget, pBackBuffer);
1492 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1493 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1494 pBackBuffer = NULL;
1496 CHECK_REFCOUNT(device, --refcount);
1498 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1499 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1500 CHECK_REFCOUNT(pSwapChain, 1);
1501 if (pStencilSurface)
1503 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1504 CHECK_REFCOUNT( pStencilSurface, 1);
1506 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1507 CHECK_REFCOUNT(device, refcount);
1508 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1509 CHECK_REFCOUNT(device, refcount);
1511 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1512 CHECK_REFCOUNT(device, --refcount);
1514 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1515 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1516 CHECK_REFCOUNT(device, ++refcount);
1517 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1518 CHECK_REFCOUNT(device, --refcount);
1519 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1520 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1521 pStencilSurface = NULL;
1524 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1525 CHECK_REFCOUNT(device, --refcount);
1526 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1527 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1529 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1530 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1531 CHECK_REFCOUNT(device, ++refcount);
1532 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1533 CHECK_REFCOUNT(device, --refcount);
1534 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1535 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1536 pSwapChain = NULL;
1539 /* Buffers */
1540 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1541 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1542 if(pIndexBuffer)
1544 tmp = get_refcount((IUnknown *)pIndexBuffer);
1546 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1547 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1548 hr = IDirect3DDevice9_SetIndices(device, NULL);
1549 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1552 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1553 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1554 if(pVertexBuffer)
1556 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1557 UINT offset = ~0;
1558 UINT stride = ~0;
1560 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1562 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1563 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1564 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1565 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1567 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1568 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1569 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1570 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1571 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1573 /* Shaders */
1574 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1575 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1576 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1577 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1578 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1579 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1580 /* Textures */
1581 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1582 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1583 if (pTexture)
1585 tmp = get_refcount( (IUnknown *)pTexture );
1587 /* SetTexture should not increase refcounts */
1588 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1589 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1590 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1591 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1593 /* This should not increment device refcount */
1594 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1595 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1596 /* But should increment texture's refcount */
1597 CHECK_REFCOUNT( pTexture, tmp+1 );
1598 /* Because the texture and surface refcount are identical */
1599 if (pTextureLevel)
1601 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1602 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1603 CHECK_REFCOUNT ( pTexture , tmp+2 );
1604 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1605 CHECK_REFCOUNT ( pTexture , tmp+1 );
1606 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1607 CHECK_REFCOUNT ( pTextureLevel, tmp );
1610 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1611 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1612 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1613 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1614 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1615 if (pVolumeTexture)
1617 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1619 /* This should not increment device refcount */
1620 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1621 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1622 /* But should increment volume texture's refcount */
1623 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1624 /* Because the volume texture and volume refcount are identical */
1625 if (pVolumeLevel)
1627 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1628 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1629 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1630 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1631 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1632 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1633 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1636 /* Surfaces */
1637 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1638 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1639 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1640 CHECK_REFCOUNT( pStencilSurface, 1 );
1641 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1642 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1643 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1644 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1645 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1646 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1647 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1648 CHECK_REFCOUNT( pRenderTarget3, 1 );
1649 /* Misc */
1650 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1651 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1653 memset(&d3dpp, 0, sizeof(d3dpp));
1654 d3dpp.Windowed = TRUE;
1655 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1656 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1657 d3dpp.EnableAutoDepthStencil = TRUE;
1658 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1659 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1660 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1661 if (pSwapChain)
1663 /* check implicit back buffer */
1664 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1665 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1666 CHECK_REFCOUNT(pSwapChain, 1);
1667 if (pBackBuffer)
1669 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1670 CHECK_REFCOUNT(pBackBuffer, 1);
1671 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1672 CHECK_REFCOUNT(device, --refcount);
1674 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1675 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1676 CHECK_REFCOUNT(device, ++refcount);
1677 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1678 CHECK_REFCOUNT(device, --refcount);
1679 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1680 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1681 pBackBuffer = NULL;
1683 CHECK_REFCOUNT(pSwapChain, 1);
1685 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1686 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1688 hr = IDirect3DDevice9_BeginStateBlock(device);
1689 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1690 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1691 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1693 /* The implicit render target is not freed if refcount reaches 0.
1694 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1695 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1696 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1697 if (pRenderTarget2)
1699 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1700 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1701 pRenderTarget, pRenderTarget2);
1702 CHECK_REFCOUNT(device, --refcount);
1703 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1704 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1705 pRenderTarget2 = NULL;
1707 pRenderTarget = NULL;
1709 cleanup:
1710 CHECK_RELEASE(device, device, --refcount);
1712 /* Buffers */
1713 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1714 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1715 /* Shaders */
1716 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1717 CHECK_RELEASE(pVertexShader, device, --refcount);
1718 CHECK_RELEASE(pPixelShader, device, --refcount);
1719 /* Textures */
1720 CHECK_RELEASE(pTextureLevel, device, --refcount);
1721 CHECK_RELEASE(pCubeTexture, device, --refcount);
1722 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1723 /* Surfaces */
1724 CHECK_RELEASE(pStencilSurface, device, --refcount);
1725 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1726 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1727 /* Misc */
1728 CHECK_RELEASE(pStateBlock, device, --refcount);
1729 CHECK_RELEASE(pSwapChain, device, --refcount);
1730 CHECK_RELEASE(pQuery, device, --refcount);
1731 /* This will destroy device - cannot check the refcount here */
1732 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1733 CHECK_RELEASE_REFCOUNT(d3d, 0);
1734 DestroyWindow(window);
1737 static void test_cursor(void)
1739 IDirect3DSurface9 *cursor = NULL;
1740 IDirect3DDevice9 *device;
1741 CURSORINFO info;
1742 IDirect3D9 *d3d;
1743 ULONG refcount;
1744 HCURSOR cur;
1745 HWND window;
1746 HRESULT hr;
1747 BOOL ret;
1749 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1750 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1751 ok(!!window, "Failed to create a window.\n");
1753 ret = SetCursorPos(50, 50);
1754 ok(ret, "Failed to set cursor position.\n");
1755 flush_events();
1756 memset(&info, 0, sizeof(info));
1757 info.cbSize = sizeof(info);
1758 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1759 cur = info.hCursor;
1761 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1762 ok(!!d3d, "Failed to create a D3D object.\n");
1763 if (!(device = create_device(d3d, window, NULL)))
1765 skip("Failed to create a 3D device, skipping test.\n");
1766 goto cleanup;
1769 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1770 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1771 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1773 /* Initially hidden */
1774 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1775 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1777 /* Not enabled without a surface*/
1778 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1779 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1781 /* Fails */
1782 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1783 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1785 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1786 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1788 IDirect3DSurface9_Release(cursor);
1790 memset(&info, 0, sizeof(info));
1791 info.cbSize = sizeof(info);
1792 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1793 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1794 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1796 /* Still hidden */
1797 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1798 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1800 /* Enabled now*/
1801 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1802 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1804 memset(&info, 0, sizeof(info));
1805 info.cbSize = sizeof(info);
1806 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1807 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1808 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1810 refcount = IDirect3DDevice9_Release(device);
1811 ok(!refcount, "Device has %u references left.\n", refcount);
1812 cleanup:
1813 IDirect3D9_Release(d3d);
1814 DestroyWindow(window);
1817 static void test_reset(void)
1819 HRESULT hr;
1820 RECT winrect;
1821 D3DPRESENT_PARAMETERS d3dpp;
1822 D3DDISPLAYMODE d3ddm, d3ddm2;
1823 D3DVIEWPORT9 vp;
1824 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1825 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1826 IDirect3DSurface9 *surface;
1827 IDirect3DTexture9 *texture;
1828 IDirect3DVertexShader9 *shader;
1829 UINT i, adapter_mode_count;
1830 D3DLOCKED_RECT lockrect;
1831 IDirect3DDevice9 *device1 = NULL;
1832 IDirect3DDevice9 *device2 = NULL;
1833 IDirect3DSwapChain9 *swapchain;
1834 struct device_desc device_desc;
1835 DEVMODEW devmode;
1836 IDirect3D9 *d3d;
1837 D3DCAPS9 caps;
1838 DWORD value;
1839 HWND hwnd;
1840 LONG ret;
1841 struct
1843 UINT w;
1844 UINT h;
1845 } *modes = NULL;
1846 UINT mode_count = 0;
1848 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1849 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1850 ok(!!hwnd, "Failed to create a window.\n");
1851 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1852 ok(!!d3d, "Failed to create a D3D object.\n");
1854 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1855 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1856 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1857 for(i = 0; i < adapter_mode_count; ++i)
1859 UINT j;
1860 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1861 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1862 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1864 for (j = 0; j < mode_count; ++j)
1866 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1867 break;
1869 if (j == mode_count)
1871 modes[j].w = d3ddm2.Width;
1872 modes[j].h = d3ddm2.Height;
1873 ++mode_count;
1876 /* We use them as invalid modes */
1877 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1878 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1879 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1880 d3ddm2.Width, d3ddm2.Height);
1881 goto cleanup;
1885 if (mode_count < 2)
1887 skip("Less than 2 modes supported, skipping mode tests\n");
1888 goto cleanup;
1891 i = 0;
1892 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1894 device_desc.width = modes[i].w;
1895 device_desc.height = modes[i].h;
1896 device_desc.device_window = hwnd;
1897 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1898 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1900 skip("Failed to create a D3D device, skipping tests.\n");
1901 goto cleanup;
1903 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1904 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1906 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1907 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1909 width = GetSystemMetrics(SM_CXSCREEN);
1910 height = GetSystemMetrics(SM_CYSCREEN);
1911 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1912 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1914 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1915 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1916 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1917 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1918 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1919 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1920 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1921 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1923 i = 1;
1924 vp.X = 10;
1925 vp.Y = 20;
1926 vp.MinZ = 2;
1927 vp.MaxZ = 3;
1928 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1929 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1931 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1932 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1933 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1934 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1935 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1937 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1938 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1939 d3dpp.Windowed = FALSE;
1940 d3dpp.BackBufferWidth = modes[i].w;
1941 d3dpp.BackBufferHeight = modes[i].h;
1942 d3dpp.BackBufferFormat = d3ddm.Format;
1943 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1944 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1945 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1946 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1948 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1949 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1950 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1952 ZeroMemory(&vp, sizeof(vp));
1953 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1954 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1955 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1956 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1957 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1958 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1959 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1960 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1962 width = GetSystemMetrics(SM_CXSCREEN);
1963 height = GetSystemMetrics(SM_CYSCREEN);
1964 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1965 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1967 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1968 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1969 memset(&d3dpp, 0, sizeof(d3dpp));
1970 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1971 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1972 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1973 d3dpp.BackBufferWidth, modes[i].w);
1974 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1975 d3dpp.BackBufferHeight, modes[i].h);
1976 IDirect3DSwapChain9_Release(swapchain);
1978 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1979 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1980 d3dpp.Windowed = TRUE;
1981 d3dpp.BackBufferWidth = 400;
1982 d3dpp.BackBufferHeight = 300;
1983 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1984 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1985 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1986 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1987 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1989 width = GetSystemMetrics(SM_CXSCREEN);
1990 height = GetSystemMetrics(SM_CYSCREEN);
1991 ok(width == orig_width, "Screen width is %d\n", width);
1992 ok(height == orig_height, "Screen height is %d\n", height);
1994 ZeroMemory(&vp, sizeof(vp));
1995 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1996 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1997 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1998 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1999 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
2000 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
2001 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2002 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2004 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2005 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2006 memset(&d3dpp, 0, sizeof(d3dpp));
2007 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2008 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2009 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2010 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2011 IDirect3DSwapChain9_Release(swapchain);
2013 memset(&devmode, 0, sizeof(devmode));
2014 devmode.dmSize = sizeof(devmode);
2015 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2016 devmode.dmPelsWidth = modes[1].w;
2017 devmode.dmPelsHeight = modes[1].h;
2018 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2019 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2020 width = GetSystemMetrics(SM_CXSCREEN);
2021 height = GetSystemMetrics(SM_CYSCREEN);
2022 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2023 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2025 d3dpp.BackBufferWidth = 500;
2026 d3dpp.BackBufferHeight = 400;
2027 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
2028 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2029 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed, hr %#x.\n", hr);
2030 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2031 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x.\n", hr);
2033 width = GetSystemMetrics(SM_CXSCREEN);
2034 height = GetSystemMetrics(SM_CYSCREEN);
2035 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2036 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2038 ZeroMemory(&vp, sizeof(vp));
2039 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2040 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed, hr %#x.\n", hr);
2041 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
2042 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
2043 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
2044 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
2045 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
2046 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
2048 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2049 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2050 memset(&d3dpp, 0, sizeof(d3dpp));
2051 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2052 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2053 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2054 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2055 IDirect3DSwapChain9_Release(swapchain);
2057 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2058 devmode.dmPelsWidth = orig_width;
2059 devmode.dmPelsHeight = orig_height;
2060 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2061 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2062 width = GetSystemMetrics(SM_CXSCREEN);
2063 height = GetSystemMetrics(SM_CYSCREEN);
2064 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
2065 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
2067 SetRect(&winrect, 0, 0, 200, 150);
2068 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
2069 ok(SetWindowPos(hwnd, NULL, 0, 0,
2070 winrect.right-winrect.left,
2071 winrect.bottom-winrect.top,
2072 SWP_NOMOVE|SWP_NOZORDER),
2073 "SetWindowPos failed\n");
2075 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2076 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2077 d3dpp.Windowed = TRUE;
2078 d3dpp.BackBufferWidth = 0;
2079 d3dpp.BackBufferHeight = 0;
2080 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
2081 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2082 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2083 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2084 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2086 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2087 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2088 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2089 d3dpp.BackBufferFormat, d3ddm.Format);
2090 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2091 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2092 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2093 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2094 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
2095 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2096 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2097 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2098 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2099 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2100 d3dpp.FullScreen_RefreshRateInHz);
2101 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2103 ZeroMemory(&vp, sizeof(vp));
2104 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2105 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
2106 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
2107 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
2108 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
2109 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
2110 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2111 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2113 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2114 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2115 memset(&d3dpp, 0, sizeof(d3dpp));
2116 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2117 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2118 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2119 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2120 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2121 d3dpp.BackBufferFormat, d3ddm.Format);
2122 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2123 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2124 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2125 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2126 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
2127 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2128 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2129 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2130 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2131 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2132 d3dpp.FullScreen_RefreshRateInHz);
2133 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2134 IDirect3DSwapChain9_Release(swapchain);
2136 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2137 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2138 d3dpp.Windowed = TRUE;
2139 d3dpp.BackBufferWidth = 400;
2140 d3dpp.BackBufferHeight = 300;
2142 /* _Reset fails if there is a resource in the default pool */
2143 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
2144 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2145 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2146 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2147 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2148 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2149 IDirect3DSurface9_Release(surface);
2150 /* Reset again to get the device out of the lost state */
2151 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2152 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2153 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2154 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2156 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
2158 IDirect3DVolumeTexture9 *volume_texture;
2160 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
2161 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
2162 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
2163 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2164 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2165 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2166 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
2167 hr, D3DERR_DEVICENOTRESET);
2168 IDirect3DVolumeTexture9_Release(volume_texture);
2169 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2170 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
2171 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2172 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2174 else
2176 skip("Volume textures not supported.\n");
2179 /* Scratch, sysmem and managed pools are fine */
2180 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2181 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2182 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2183 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2184 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2185 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2186 IDirect3DSurface9_Release(surface);
2188 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2189 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2190 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2191 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2192 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2193 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2194 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2195 IDirect3DSurface9_Release(surface);
2197 /* The depth stencil should get reset to the auto depth stencil when present. */
2198 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2199 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2201 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2202 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2203 ok(surface == NULL, "Depth stencil should be NULL\n");
2205 d3dpp.EnableAutoDepthStencil = TRUE;
2206 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2207 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2208 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2210 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2211 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2212 ok(surface != NULL, "Depth stencil should not be NULL\n");
2213 if (surface) IDirect3DSurface9_Release(surface);
2215 d3dpp.EnableAutoDepthStencil = FALSE;
2216 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2217 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2219 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2220 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2221 ok(surface == NULL, "Depth stencil should be NULL\n");
2223 /* Will a sysmem or scratch survive while locked */
2224 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2225 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2226 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2227 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2228 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2229 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2230 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2231 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2232 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2233 IDirect3DSurface9_UnlockRect(surface);
2234 IDirect3DSurface9_Release(surface);
2236 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2237 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2238 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2239 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2240 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2241 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2242 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2243 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2244 IDirect3DSurface9_UnlockRect(surface);
2245 IDirect3DSurface9_Release(surface);
2247 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2248 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2249 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2250 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2251 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2252 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2253 IDirect3DTexture9_Release(texture);
2255 /* A reference held to an implicit surface causes failures as well */
2256 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2257 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2258 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2259 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2260 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2261 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2262 IDirect3DSurface9_Release(surface);
2263 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2264 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2265 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2266 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2268 /* Shaders are fine as well */
2269 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2270 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2271 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2272 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2273 IDirect3DVertexShader9_Release(shader);
2275 /* Try setting invalid modes */
2276 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2277 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2278 d3dpp.Windowed = FALSE;
2279 d3dpp.BackBufferWidth = 32;
2280 d3dpp.BackBufferHeight = 32;
2281 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2282 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2283 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2284 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2286 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2287 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2288 d3dpp.Windowed = FALSE;
2289 d3dpp.BackBufferWidth = 801;
2290 d3dpp.BackBufferHeight = 600;
2291 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2292 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2293 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2294 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2296 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2297 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2298 d3dpp.Windowed = FALSE;
2299 d3dpp.BackBufferWidth = 0;
2300 d3dpp.BackBufferHeight = 0;
2301 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2302 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2303 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2304 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2306 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2308 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2309 d3dpp.Windowed = TRUE;
2310 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2311 d3dpp.BackBufferFormat = d3ddm.Format;
2312 d3dpp.EnableAutoDepthStencil = FALSE;
2313 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2315 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2316 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2318 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2319 goto cleanup;
2322 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2323 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2325 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2326 d3dpp.Windowed = TRUE;
2327 d3dpp.BackBufferWidth = 400;
2328 d3dpp.BackBufferHeight = 300;
2329 d3dpp.EnableAutoDepthStencil = TRUE;
2330 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2332 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2333 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2335 if (FAILED(hr)) goto cleanup;
2337 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2338 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2339 ok(surface != NULL, "Depth stencil should not be NULL\n");
2340 if (surface) IDirect3DSurface9_Release(surface);
2342 cleanup:
2343 HeapFree(GetProcessHeap(), 0, modes);
2344 if (device2)
2346 UINT refcount = IDirect3DDevice9_Release(device2);
2347 ok(!refcount, "Device has %u references left.\n", refcount);
2349 if (device1)
2351 UINT refcount = IDirect3DDevice9_Release(device1);
2352 ok(!refcount, "Device has %u references left.\n", refcount);
2354 IDirect3D9_Release(d3d);
2355 DestroyWindow(hwnd);
2358 /* Test adapter display modes */
2359 static void test_display_modes(void)
2361 D3DDISPLAYMODE dmode;
2362 IDirect3D9 *d3d;
2364 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2365 ok(!!d3d, "Failed to create a D3D object.\n");
2367 #define TEST_FMT(x,r) do { \
2368 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2369 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2370 } while(0)
2372 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2373 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2374 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2375 /* D3DFMT_R5G6B5 */
2376 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2377 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2378 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2379 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2380 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2381 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2382 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2383 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2384 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2385 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2386 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2387 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2389 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2390 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2392 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2393 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2394 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2396 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2397 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2398 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2399 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2400 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2401 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2403 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2404 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2405 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2406 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2407 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2408 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2409 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2410 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2411 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2412 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2414 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2415 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2416 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2417 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2418 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2419 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2420 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2421 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2422 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2423 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2425 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2426 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2427 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2428 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2429 /* Floating point formats */
2430 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2431 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2432 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2434 /* IEEE formats */
2435 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2436 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2437 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2439 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2441 TEST_FMT(0, D3DERR_INVALIDCALL);
2443 IDirect3D9_Release(d3d);
2446 static void test_scene(void)
2448 IDirect3DSurface9 *surface1, *surface2, *surface3;
2449 IDirect3DSurface9 *backBuffer, *rt, *ds;
2450 RECT rect = {0, 0, 128, 128};
2451 IDirect3DDevice9 *device;
2452 IDirect3D9 *d3d;
2453 ULONG refcount;
2454 D3DCAPS9 caps;
2455 HWND window;
2456 HRESULT hr;
2458 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2459 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2460 ok(!!window, "Failed to create a window.\n");
2461 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2462 ok(!!d3d, "Failed to create a D3D object.\n");
2463 if (!(device = create_device(d3d, window, NULL)))
2465 skip("Failed to create a 3D device, skipping test.\n");
2466 goto cleanup;
2469 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2470 memset(&caps, 0, sizeof(caps));
2471 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2472 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2474 /* Test an EndScene without BeginScene. Should return an error */
2475 hr = IDirect3DDevice9_EndScene(device);
2476 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2478 /* Test a normal BeginScene / EndScene pair, this should work */
2479 hr = IDirect3DDevice9_BeginScene(device);
2480 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2481 hr = IDirect3DDevice9_EndScene(device);
2482 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2484 /* Test another EndScene without having begun a new scene. Should return an error */
2485 hr = IDirect3DDevice9_EndScene(device);
2486 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2488 /* Two nested BeginScene and EndScene calls */
2489 hr = IDirect3DDevice9_BeginScene(device);
2490 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2491 hr = IDirect3DDevice9_BeginScene(device);
2492 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2493 hr = IDirect3DDevice9_EndScene(device);
2494 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2495 hr = IDirect3DDevice9_EndScene(device);
2496 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2498 /* Create some surfaces to test stretchrect between the scenes */
2499 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2500 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2501 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2502 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2503 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2504 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2505 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2506 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2507 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2508 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2509 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2510 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2512 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2513 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2514 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2515 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2517 /* First make sure a simple StretchRect call works */
2518 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2519 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2520 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2521 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2522 if (0) /* Disabled for now because it crashes in wine */
2524 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2525 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2526 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2529 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2530 * BeginScene - Endscene pair with normal surfaces and render targets, but
2531 * not depth stencil surfaces. */
2532 hr = IDirect3DDevice9_BeginScene(device);
2533 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2535 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2536 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2537 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2538 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2539 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2540 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2541 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2543 hr = IDirect3DDevice9_EndScene(device);
2544 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2546 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2547 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2548 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2550 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2551 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2552 hr = IDirect3DDevice9_BeginScene(device);
2553 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2554 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2555 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2556 hr = IDirect3DDevice9_EndScene(device);
2557 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2559 IDirect3DSurface9_Release(rt);
2560 IDirect3DSurface9_Release(ds);
2561 IDirect3DSurface9_Release(backBuffer);
2562 IDirect3DSurface9_Release(surface1);
2563 IDirect3DSurface9_Release(surface2);
2564 IDirect3DSurface9_Release(surface3);
2565 refcount = IDirect3DDevice9_Release(device);
2566 ok(!refcount, "Device has %u references left.\n", refcount);
2567 cleanup:
2568 IDirect3D9_Release(d3d);
2569 DestroyWindow(window);
2572 static void test_limits(void)
2574 IDirect3DTexture9 *texture;
2575 IDirect3DDevice9 *device;
2576 IDirect3D9 *d3d;
2577 unsigned int i;
2578 ULONG refcount;
2579 HWND window;
2580 HRESULT hr;
2582 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2583 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2584 ok(!!window, "Failed to create a window.\n");
2585 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2586 ok(!!d3d, "Failed to create a D3D object.\n");
2587 if (!(device = create_device(d3d, window, NULL)))
2589 skip("Failed to create a 3D device, skipping test.\n");
2590 goto cleanup;
2593 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2594 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2596 /* There are 16 pixel samplers. We should be able to access all of them */
2597 for (i = 0; i < 16; ++i)
2599 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2600 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2601 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2602 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2603 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2604 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2607 /* Now test all 8 textures stage states */
2608 for (i = 0; i < 8; ++i)
2610 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2611 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2614 /* Investigations show that accessing higher samplers / textures stage
2615 * states does not return an error either. Writing to too high samplers
2616 * (approximately sampler 40) causes memory corruption in Windows, so
2617 * there is no bounds checking. */
2618 IDirect3DTexture9_Release(texture);
2619 refcount = IDirect3D9_Release(device);
2620 ok(!refcount, "Device has %u references left.\n", refcount);
2621 cleanup:
2622 IDirect3D9_Release(d3d);
2623 DestroyWindow(window);
2626 static void test_depthstenciltest(void)
2628 HRESULT hr;
2629 IDirect3DDevice9 *pDevice = NULL;
2630 D3DPRESENT_PARAMETERS d3dpp;
2631 D3DDISPLAYMODE d3ddm;
2632 IDirect3DSurface9 *pDepthStencil = NULL;
2633 IDirect3DSurface9 *pDepthStencil2 = NULL;
2634 IDirect3D9 *d3d;
2635 DWORD state;
2636 HWND hwnd;
2638 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2639 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2640 ok(!!hwnd, "Failed to create a window.\n");
2641 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2642 ok(!!d3d, "Failed to create a D3D object.\n");
2644 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2645 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2646 d3dpp.Windowed = TRUE;
2647 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2648 d3dpp.BackBufferWidth = 800;
2649 d3dpp.BackBufferHeight = 600;
2650 d3dpp.BackBufferFormat = d3ddm.Format;
2651 d3dpp.EnableAutoDepthStencil = TRUE;
2652 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2654 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2655 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2656 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2657 if(!pDevice)
2659 skip("Failed to create a d3d device\n");
2660 goto cleanup;
2663 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2664 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2666 /* Try to clear */
2667 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2668 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2670 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2671 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2673 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2674 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2675 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2676 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2678 /* This left the render states untouched! */
2679 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2680 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2681 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2682 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2683 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2684 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2685 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2686 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2687 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2688 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2689 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2690 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2692 /* This is supposed to fail now */
2693 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2694 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2696 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2697 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2699 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2700 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2702 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2703 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2704 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2706 /* Now it works again */
2707 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2708 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2710 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2711 if(pDevice) IDirect3D9_Release(pDevice);
2713 /* Now see if autodepthstencil disable is honored. First, without a format set */
2714 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2715 d3dpp.Windowed = TRUE;
2716 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2717 d3dpp.BackBufferWidth = 800;
2718 d3dpp.BackBufferHeight = 600;
2719 d3dpp.BackBufferFormat = d3ddm.Format;
2720 d3dpp.EnableAutoDepthStencil = FALSE;
2721 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2723 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2724 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2725 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2726 if(!pDevice)
2728 skip("Failed to create a d3d device\n");
2729 goto cleanup;
2732 pDepthStencil = NULL;
2733 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2734 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2735 if(pDepthStencil) {
2736 IDirect3DSurface9_Release(pDepthStencil);
2737 pDepthStencil = NULL;
2740 /* Check the depth test state */
2741 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2742 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2743 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2745 if(pDevice) IDirect3D9_Release(pDevice);
2747 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2748 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2749 d3dpp.Windowed = TRUE;
2750 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2751 d3dpp.BackBufferWidth = 800;
2752 d3dpp.BackBufferHeight = 600;
2753 d3dpp.BackBufferFormat = d3ddm.Format;
2754 d3dpp.EnableAutoDepthStencil = FALSE;
2755 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2757 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2758 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2759 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2760 if(!pDevice)
2762 skip("Failed to create a d3d device\n");
2763 goto cleanup;
2766 pDepthStencil = NULL;
2767 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2768 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2769 if(pDepthStencil) {
2770 IDirect3DSurface9_Release(pDepthStencil);
2771 pDepthStencil = NULL;
2774 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2775 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2776 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2778 cleanup:
2779 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2780 if (pDevice)
2782 UINT refcount = IDirect3D9_Release(pDevice);
2783 ok(!refcount, "Device has %u references left.\n", refcount);
2785 IDirect3D9_Release(d3d);
2786 DestroyWindow(hwnd);
2789 static void test_get_rt(void)
2791 IDirect3DSurface9 *backbuffer, *rt;
2792 IDirect3DDevice9 *device;
2793 IDirect3D9 *d3d9;
2794 D3DCAPS9 caps;
2795 HWND window;
2796 HRESULT hr;
2797 ULONG ref;
2798 UINT i;
2800 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2801 0, 0, 128, 128, 0, 0, 0, 0);
2802 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2803 ok(!!d3d9, "Failed to create a D3D object.\n");
2804 device = create_device(d3d9, window, NULL);
2805 if (!device)
2807 skip("Failed to create a D3D device, skipping tests.\n");
2808 goto done;
2811 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2812 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2813 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2815 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2816 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2818 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2820 rt = backbuffer;
2821 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2822 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2823 ok(!rt, "Got rt %p.\n", rt);
2826 IDirect3DSurface9_Release(backbuffer);
2828 ref = IDirect3DDevice9_Release(device);
2829 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2830 done:
2831 IDirect3D9_Release(d3d9);
2832 DestroyWindow(window);
2835 static void test_draw_primitive(void)
2837 static const struct
2839 float position[3];
2840 DWORD color;
2842 quad[] =
2844 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2845 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2846 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2847 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2849 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
2850 static const D3DVERTEXELEMENT9 decl_elements[] =
2852 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2853 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2854 D3DDECL_END()
2857 IDirect3DVertexDeclaration9 *vertex_declaration;
2858 IDirect3DVertexBuffer9 *vertex_buffer;
2859 IDirect3DIndexBuffer9 *index_buffer;
2860 IDirect3DDevice9 *device;
2861 IDirect3D9 *d3d9;
2862 ULONG refcount;
2863 HWND window;
2864 HRESULT hr;
2865 void *ptr;
2867 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
2868 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2869 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2870 ok(!!d3d9, "Failed to create a D3D object.\n");
2871 if (!(device = create_device(d3d9, window, NULL)))
2873 skip("Failed to create a D3D device.\n");
2874 IDirect3D9_Release(d3d9);
2875 DestroyWindow(window);
2876 return;
2879 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2880 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
2882 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
2883 D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2884 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#x.\n", hr);
2885 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2886 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2887 memcpy(ptr, quad, sizeof(quad));
2888 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2889 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2890 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2891 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#x.\n", hr);
2893 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
2894 D3DPOOL_DEFAULT, &index_buffer, NULL);
2895 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#x.\n", hr);
2896 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2897 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2898 memcpy(ptr, indices, sizeof(indices));
2899 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2900 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2902 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2903 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#x.\n", hr);
2905 hr = IDirect3DDevice9_BeginScene(device);
2906 ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2908 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2909 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2911 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2912 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2914 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2915 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
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 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2923 /* Valid index buffer, NULL vertex declaration. Should fail */
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(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2930 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2931 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2932 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2934 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2935 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2937 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2938 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2940 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2941 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2943 /* NULL index buffer, valid vertex vertex declaration. Should succeed */
2944 hr = IDirect3DDevice9_SetIndices(device, NULL);
2945 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2946 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2947 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2948 todo_wine ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2950 /* Valid index buffer and vertex declaration. Should succeed */
2951 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2952 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2953 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2954 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2955 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2957 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2958 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2959 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#x.\n", hr);
2961 hr = IDirect3DDevice9_EndScene(device);
2962 ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2964 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2965 ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2967 IDirect3DVertexBuffer9_Release(vertex_buffer);
2968 IDirect3DIndexBuffer9_Release(index_buffer);
2969 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2970 refcount = IDirect3DDevice9_Release(device);
2971 ok(!refcount, "Device has %u references left.\n", refcount);
2972 IDirect3D9_Release(d3d9);
2973 DestroyWindow(window);
2976 static void test_null_stream(void)
2978 IDirect3DVertexBuffer9 *buffer = NULL;
2979 IDirect3DDevice9 *device;
2980 IDirect3D9 *d3d9;
2981 ULONG refcount;
2982 HWND window;
2983 HRESULT hr;
2984 IDirect3DVertexShader9 *shader = NULL;
2985 IDirect3DVertexDeclaration9 *decl = NULL;
2986 static const DWORD shader_code[] =
2988 0xfffe0101, /* vs_1_1 */
2989 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2990 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2991 0x0000ffff /* end */
2993 static const D3DVERTEXELEMENT9 decl_elements[] = {
2994 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2995 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2996 D3DDECL_END()
2999 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3000 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3001 ok(!!window, "Failed to create a window.\n");
3002 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3003 ok(!!d3d9, "Failed to create a D3D object.\n");
3004 if (!(device = create_device(d3d9, window, NULL)))
3006 skip("Failed to create a 3D device, skipping test.\n");
3007 goto cleanup;
3010 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
3011 if(FAILED(hr)) {
3012 skip("No vertex shader support\n");
3013 goto cleanup;
3015 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3016 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
3017 if (FAILED(hr)) {
3018 skip("Vertex declaration handling not possible.\n");
3019 goto cleanup;
3021 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
3022 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
3023 if (FAILED(hr)) {
3024 skip("Vertex buffer handling not possible.\n");
3025 goto cleanup;
3028 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
3029 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3030 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
3031 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3032 hr = IDirect3DDevice9_SetVertexShader(device, shader);
3033 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
3034 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3035 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
3037 hr = IDirect3DDevice9_BeginScene(device);
3038 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3039 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
3040 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3041 hr = IDirect3DDevice9_EndScene(device);
3042 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3044 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3045 IDirect3DDevice9_SetVertexShader(device, NULL);
3046 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3048 cleanup:
3049 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
3050 if (decl) IDirect3DVertexDeclaration9_Release(decl);
3051 if (shader) IDirect3DVertexShader9_Release(shader);
3052 if (device)
3054 refcount = IDirect3DDevice9_Release(device);
3055 ok(!refcount, "Device has %u references left.\n", refcount);
3057 IDirect3D9_Release(d3d9);
3058 DestroyWindow(window);
3061 static void test_lights(void)
3063 IDirect3DDevice9 *device;
3064 IDirect3D9 *d3d9;
3065 ULONG refcount;
3066 HWND window;
3067 HRESULT hr;
3068 unsigned int i;
3069 BOOL enabled;
3070 D3DCAPS9 caps;
3072 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3073 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3074 ok(!!window, "Failed to create a window.\n");
3075 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3076 ok(!!d3d9, "Failed to create a D3D object.\n");
3077 if (!(device = create_device(d3d9, window, NULL)))
3079 skip("Failed to create a 3D device, skipping test.\n");
3080 goto cleanup;
3083 memset(&caps, 0, sizeof(caps));
3084 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3085 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
3087 for(i = 1; i <= caps.MaxActiveLights; i++) {
3088 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
3089 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
3090 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
3091 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
3092 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
3095 /* TODO: Test the rendering results in this situation */
3096 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
3097 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
3098 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
3099 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
3100 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
3101 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
3102 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
3104 for(i = 1; i <= caps.MaxActiveLights; i++) {
3105 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
3106 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
3109 refcount = IDirect3DDevice9_Release(device);
3110 ok(!refcount, "Device has %u references left.\n", refcount);
3111 cleanup:
3112 IDirect3D9_Release(d3d9);
3113 DestroyWindow(window);
3116 static void test_set_stream_source(void)
3118 IDirect3DVertexBuffer9 *vb;
3119 IDirect3DDevice9 *device;
3120 IDirect3D9 *d3d9;
3121 ULONG refcount;
3122 HWND window;
3123 HRESULT hr;
3125 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3126 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3127 ok(!!window, "Failed to create a window.\n");
3128 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3129 ok(!!d3d9, "Failed to create a D3D object.\n");
3130 if (!(device = create_device(d3d9, window, NULL)))
3132 skip("Failed to create a 3D device, skipping test.\n");
3133 goto cleanup;
3136 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
3137 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
3139 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
3140 * (Radeon 9000 verified) reject them, so accept both results. Wine
3141 * currently rejects this to be able to optimize the vbo conversion, but
3142 * writes a WARN. */
3143 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
3144 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3145 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
3146 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3147 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
3148 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3149 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
3150 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3151 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
3152 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3154 /* Try to set the NULL buffer with an offset and stride 0 */
3155 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3156 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3157 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
3158 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3159 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
3160 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3161 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
3162 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3163 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
3164 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3166 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3167 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3169 IDirect3DVertexBuffer9_Release(vb);
3170 refcount = IDirect3DDevice9_Release(device);
3171 ok(!refcount, "Device has %u references left.\n", refcount);
3172 cleanup:
3173 IDirect3D9_Release(d3d9);
3174 DestroyWindow(window);
3177 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
3178 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
3179 * a fixed number of combinations are possible in fullscreen mode. In windowed
3180 * mode more combinations are allowed due to format conversion and this is
3181 * likely driver dependent. */
3182 static void test_display_formats(void)
3184 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
3185 unsigned int backbuffer, display;
3186 unsigned int windowed;
3187 IDirect3D9 *d3d9;
3188 BOOL should_pass;
3189 BOOL has_modes;
3190 HRESULT hr;
3192 static const struct
3194 const char *name;
3195 D3DFORMAT format;
3196 D3DFORMAT alpha_format;
3197 BOOL display;
3198 BOOL windowed;
3200 formats[] =
3202 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
3203 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
3204 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
3205 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
3206 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3207 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3208 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3211 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3212 ok(!!d3d9, "Failed to create a D3D object.\n");
3214 for (display = 0; display < ARRAY_SIZE(formats); ++display)
3216 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3218 for (windowed = 0; windowed <= 1; ++windowed)
3220 for (backbuffer = 0; backbuffer < ARRAY_SIZE(formats); ++backbuffer)
3222 should_pass = FALSE;
3224 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3226 D3DFORMAT backbuffer_format;
3228 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3229 backbuffer_format = formats[display].format;
3230 else
3231 backbuffer_format = formats[backbuffer].format;
3233 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3234 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3235 if (hr == D3D_OK)
3237 if (windowed)
3239 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3240 backbuffer_format, formats[display].format);
3241 should_pass = (hr == D3D_OK);
3243 else
3244 should_pass = (formats[display].format == formats[backbuffer].format
3245 || (formats[display].alpha_format
3246 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3250 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3251 formats[display].format, formats[backbuffer].format, windowed);
3252 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3253 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3254 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3259 IDirect3D9_Release(d3d9);
3262 static void test_scissor_size(void)
3264 struct device_desc device_desc;
3265 IDirect3D9 *d3d9_ptr;
3266 unsigned int i;
3267 static struct {
3268 int winx; int winy; int backx; int backy; DWORD flags;
3269 } scts[] = { /* scissor tests */
3270 {800, 600, 640, 480, 0},
3271 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3272 {640, 480, 800, 600, 0},
3273 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3276 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3277 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3279 for (i = 0; i < ARRAY_SIZE(scts); i++)
3281 IDirect3DDevice9 *device_ptr = 0;
3282 HRESULT hr;
3283 HWND hwnd = 0;
3284 RECT scissorrect;
3286 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3287 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3289 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3291 scts[i].backx = registry_mode.dmPelsWidth;
3292 scts[i].backy = registry_mode.dmPelsHeight;
3295 device_desc.device_window = hwnd;
3296 device_desc.width = scts[i].backx;
3297 device_desc.height = scts[i].backy;
3298 device_desc.flags = scts[i].flags;
3299 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3301 skip("Failed to create a 3D device, skipping test.\n");
3302 DestroyWindow(hwnd);
3303 goto err_out;
3306 /* Check for the default scissor rect size */
3307 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3308 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3309 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3310 && scissorrect.top == 0 && scissorrect.left == 0,
3311 "Scissorrect mismatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3312 scts[i].backx, scts[i].backy);
3314 /* check the scissorrect values after a reset */
3315 device_desc.width = registry_mode.dmPelsWidth;
3316 device_desc.height = registry_mode.dmPelsHeight;
3317 device_desc.flags = scts[i].flags;
3318 hr = reset_device(device_ptr, &device_desc);
3319 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3320 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3321 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3323 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3324 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3325 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3326 && scissorrect.top == 0 && scissorrect.left == 0,
3327 "Scissorrect mismatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3328 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3330 if (device_ptr)
3332 ULONG ref;
3334 ref = IDirect3DDevice9_Release(device_ptr);
3335 DestroyWindow(hwnd);
3336 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3340 err_out:
3341 IDirect3D9_Release(d3d9_ptr);
3344 static void test_multi_device(void)
3346 IDirect3DDevice9 *device1, *device2;
3347 HWND window1, window2;
3348 IDirect3D9 *d3d9;
3349 ULONG refcount;
3351 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3352 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3353 ok(!!window1, "Failed to create a window.\n");
3354 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3355 ok(!!d3d9, "Failed to create a D3D object.\n");
3356 if (!(device1 = create_device(d3d9, window1, NULL)))
3358 skip("Failed to create a 3D device, skipping test.\n");
3359 IDirect3D9_Release(d3d9);
3360 DestroyWindow(window1);
3361 return;
3363 IDirect3D9_Release(d3d9);
3365 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3366 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3367 ok(!!window2, "Failed to create a window.\n");
3368 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3369 ok(!!d3d9, "Failed to create a D3D object.\n");
3370 device2 = create_device(d3d9, window2, NULL);
3371 IDirect3D9_Release(d3d9);
3373 refcount = IDirect3DDevice9_Release(device2);
3374 ok(!refcount, "Device has %u references left.\n", refcount);
3375 refcount = IDirect3DDevice9_Release(device1);
3376 ok(!refcount, "Device has %u references left.\n", refcount);
3377 DestroyWindow(window2);
3378 DestroyWindow(window1);
3381 static HWND filter_messages;
3383 enum message_window
3385 DEVICE_WINDOW,
3386 FOCUS_WINDOW,
3389 struct message
3391 UINT message;
3392 enum message_window window;
3393 BOOL check_wparam;
3394 WPARAM expect_wparam;
3397 static const struct message *expect_messages;
3398 static HWND device_window, focus_window;
3399 static LONG windowposchanged_received, syscommand_received, wm_size_received;
3401 struct wndproc_thread_param
3403 HWND dummy_window;
3404 HANDLE window_created;
3405 HANDLE test_finished;
3406 BOOL running_in_foreground;
3409 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3411 if (filter_messages && filter_messages == hwnd)
3413 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3414 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3417 if (expect_messages)
3419 HWND w;
3421 switch (expect_messages->window)
3423 case DEVICE_WINDOW:
3424 w = device_window;
3425 break;
3427 case FOCUS_WINDOW:
3428 w = focus_window;
3429 break;
3431 default:
3432 w = NULL;
3433 break;
3436 if (hwnd == w && expect_messages->message == message)
3438 if (expect_messages->check_wparam)
3439 ok(wparam == expect_messages->expect_wparam,
3440 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3441 wparam, message, expect_messages->expect_wparam);
3443 ++expect_messages;
3447 /* KDE randomly does something with the hidden window during the
3448 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3449 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3450 * just flag WM_WINDOWPOSCHANGED as bad. */
3451 if (message == WM_WINDOWPOSCHANGED)
3452 InterlockedIncrement(&windowposchanged_received);
3453 else if (message == WM_SYSCOMMAND)
3454 InterlockedIncrement(&syscommand_received);
3455 else if (message == WM_SIZE)
3456 InterlockedIncrement(&wm_size_received);
3458 return DefWindowProcA(hwnd, message, wparam, lparam);
3461 static DWORD WINAPI wndproc_thread(void *param)
3463 struct wndproc_thread_param *p = param;
3464 DWORD res;
3465 BOOL ret;
3467 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3468 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3469 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3470 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3472 ret = SetEvent(p->window_created);
3473 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3475 for (;;)
3477 MSG msg;
3479 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3480 res = WaitForSingleObject(p->test_finished, 100);
3481 if (res == WAIT_OBJECT_0) break;
3482 if (res != WAIT_TIMEOUT)
3484 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3485 break;
3489 DestroyWindow(p->dummy_window);
3491 return 0;
3494 static void test_wndproc(void)
3496 struct wndproc_thread_param thread_params;
3497 struct device_desc device_desc;
3498 IDirect3DDevice9 *device;
3499 WNDCLASSA wc = {0};
3500 IDirect3D9 *d3d9;
3501 HANDLE thread;
3502 LONG_PTR proc;
3503 ULONG ref;
3504 DWORD res, tid;
3505 HWND tmp;
3506 UINT i, adapter_mode_count;
3507 HRESULT hr;
3508 D3DDISPLAYMODE d3ddm;
3509 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3510 DEVMODEW devmode;
3511 LONG change_ret;
3512 BOOL ret;
3514 static const struct message create_messages[] =
3516 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3517 /* Do not test wparam here. If device creation succeeds,
3518 * wparam is WA_ACTIVE. If device creation fails (testbot)
3519 * wparam is set to WA_INACTIVE on some Windows versions. */
3520 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3521 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3522 {0, 0, FALSE, 0},
3524 static const struct message focus_loss_messages[] =
3526 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3527 * not reliable on X11 WMs. When the window focus follows the
3528 * mouse pointer the message is not sent.
3529 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3530 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3531 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3532 * not deterministic. */
3533 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3534 /* Windows sends WM_ACTIVATE to the device window, indicating that
3535 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3536 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3537 * leaves the device window active, breaking re-activation in the
3538 * lost device test.
3539 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3540 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3541 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3542 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3543 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3544 * not deterministic. It may be sent after the focus window handling
3545 * or before. */
3546 {0, 0, FALSE, 0},
3548 static const struct message focus_loss_messages_nowc[] =
3550 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3551 * not reliable on X11 WMs. When the window focus follows the
3552 * mouse pointer the message is not sent.
3553 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3554 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3555 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3556 {0, 0, FALSE, 0},
3558 static const struct message reactivate_messages[] =
3560 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3561 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3562 /* optional WM_MOVE here if size changed */
3563 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3564 {0, 0, FALSE, 0},
3566 static const struct message reactivate_messages_nowc[] =
3568 /* We're activating the device window before activating the
3569 * focus window, so no ACTIVATEAPP message is sent. */
3570 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3571 {0, 0, FALSE, 0},
3573 static const struct message focus_loss_messages_hidden[] =
3575 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3576 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3577 {0, 0, FALSE, 0},
3579 static const struct message focus_loss_messages_filtered[] =
3581 /* WM_ACTIVATE is delivered to the window proc because it is
3582 * generated by SetForegroundWindow before the d3d routine
3583 * starts it work. Don't check for it due to focus-follows-mouse
3584 * WMs though. */
3585 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3586 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3587 {0, 0, FALSE, 0},
3589 static const struct message reactivate_messages_filtered[] =
3591 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3592 {0, 0, FALSE, 0},
3594 static const struct message sc_restore_messages[] =
3596 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3597 * processed it. Our wndproc has no way to prevent d3d from
3598 * handling the message. The second DefWindowProc call done by
3599 * our wndproc doesn't do any changes to the window because it
3600 * is already restored due to d3d's handling. */
3601 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3602 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3603 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3604 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3605 {0, 0, FALSE, 0},
3607 static const struct message sc_minimize_messages[] =
3609 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3610 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3611 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3612 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3613 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3614 {0, 0, FALSE, 0},
3616 static const struct message sc_maximize_messages[] =
3618 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3619 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3620 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3621 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3622 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3623 {0, 0, FALSE, 0},
3625 static const struct
3627 DWORD create_flags;
3628 const struct message *focus_loss_messages, *reactivate_messages;
3629 BOOL iconic;
3631 tests[] =
3633 {0, focus_loss_messages, reactivate_messages, TRUE},
3634 {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, reactivate_messages_nowc, FALSE},
3637 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3638 ok(!!d3d9, "Failed to create a D3D object.\n");
3640 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3641 for (i = 0; i < adapter_mode_count; ++i)
3643 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3644 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3646 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3647 continue;
3648 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3649 * refuses to create a device at these sizes. */
3650 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3651 continue;
3653 if (!user32_width)
3655 user32_width = d3ddm.Width;
3656 user32_height = d3ddm.Height;
3657 continue;
3660 /* Make sure the d3d mode is smaller in width or height and at most
3661 * equal in the other dimension than the mode passed to
3662 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3663 * the ChangeDisplaySettings parameters + 12. */
3664 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3665 continue;
3666 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3668 d3d_width = d3ddm.Width;
3669 d3d_height = d3ddm.Height;
3670 break;
3672 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3674 d3d_width = user32_width;
3675 d3d_height = user32_height;
3676 user32_width = d3ddm.Width;
3677 user32_height = d3ddm.Height;
3678 break;
3682 if (!d3d_width)
3684 skip("Could not find adequate modes, skipping mode tests.\n");
3685 IDirect3D9_Release(d3d9);
3686 return;
3689 wc.lpfnWndProc = test_proc;
3690 wc.lpszClassName = "d3d9_test_wndproc_wc";
3691 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3693 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3694 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3695 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3696 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3698 memset(&devmode, 0, sizeof(devmode));
3699 devmode.dmSize = sizeof(devmode);
3700 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3702 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3703 devmode.dmPelsWidth = user32_width;
3704 devmode.dmPelsHeight = user32_height;
3705 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3706 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3708 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3709 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3710 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3711 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3712 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3713 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3715 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3716 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3718 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3719 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3720 (LONG_PTR)test_proc, proc);
3721 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3722 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3723 (LONG_PTR)test_proc, proc);
3725 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3726 device_window, focus_window, thread_params.dummy_window);
3728 tmp = GetFocus();
3729 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3730 if (thread_params.running_in_foreground)
3732 tmp = GetForegroundWindow();
3733 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3734 thread_params.dummy_window, tmp);
3736 else
3737 skip("Not running in foreground, skip foreground window test\n");
3739 flush_events();
3741 expect_messages = create_messages;
3743 device_desc.device_window = device_window;
3744 device_desc.width = d3d_width;
3745 device_desc.height = d3d_height;
3746 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3747 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3749 skip("Failed to create a D3D device, skipping tests.\n");
3750 goto done;
3753 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3754 expect_messages->message, expect_messages->window, i);
3755 expect_messages = NULL;
3757 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3759 tmp = GetFocus();
3760 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3761 tmp = GetForegroundWindow();
3762 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3764 SetForegroundWindow(focus_window);
3765 flush_events();
3767 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3768 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3769 (LONG_PTR)test_proc, proc, i);
3771 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3772 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3773 (LONG_PTR)test_proc, i);
3775 /* Change the mode while the device is in use and then drop focus. */
3776 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3777 devmode.dmPelsWidth = user32_width;
3778 devmode.dmPelsHeight = user32_height;
3779 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3780 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3782 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3783 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3784 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3785 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3786 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3787 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3789 expect_messages = tests[i].focus_loss_messages;
3790 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3791 * manually changing the focus. It generates the same messages, but the task
3792 * bar still shows the previous foreground window as active, and the window has
3793 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3794 * the device is difficult, see below. */
3795 SetForegroundWindow(GetDesktopWindow());
3796 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3797 expect_messages->message, expect_messages->window, i);
3798 expect_messages = NULL;
3799 tmp = GetFocus();
3800 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3801 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3803 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3804 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3806 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3807 ok(ret, "Failed to get display mode.\n");
3808 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3809 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3810 devmode.dmPelsWidth, devmode.dmPelsHeight);
3812 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3813 * done before the focus window is restored. This makes sense to some extent
3814 * because minimizing the window on focus loss is the application's job if this
3815 * flag is set. */
3816 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3818 ShowWindow(device_window, SW_MINIMIZE);
3819 ShowWindow(device_window, SW_RESTORE);
3821 flush_events();
3823 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3824 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3825 * restore is triggered by the user. */
3826 expect_messages = tests[i].reactivate_messages;
3827 ShowWindow(focus_window, SW_MINIMIZE);
3828 ShowWindow(focus_window, SW_RESTORE);
3829 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3830 SetForegroundWindow(focus_window);
3831 flush_events();
3832 SetForegroundWindow(focus_window);
3833 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3834 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3835 expect_messages->message, expect_messages->window, i);
3836 expect_messages = NULL;
3838 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3839 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3841 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3842 ok(ret, "Failed to get display mode.\n");
3843 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3844 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3845 devmode.dmPelsWidth, devmode.dmPelsHeight);
3847 hr = reset_device(device, &device_desc);
3848 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3850 ShowWindow(device_window, SW_HIDE);
3851 flush_events();
3853 expect_messages = focus_loss_messages_hidden;
3854 windowposchanged_received = 0;
3855 SetForegroundWindow(GetDesktopWindow());
3856 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3857 expect_messages->message, expect_messages->window, i);
3858 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3859 expect_messages = NULL;
3860 flush_events();
3862 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3863 ok(ret, "Failed to get display mode.\n");
3864 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3865 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3867 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3868 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3869 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3870 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3871 flush_events();
3873 syscommand_received = 0;
3874 expect_messages = sc_restore_messages;
3875 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3876 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3877 expect_messages->message, expect_messages->window, i);
3878 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3879 expect_messages = NULL;
3880 flush_events();
3882 expect_messages = sc_minimize_messages;
3883 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3884 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3885 expect_messages->message, expect_messages->window, i);
3886 expect_messages = NULL;
3887 flush_events();
3889 expect_messages = sc_maximize_messages;
3890 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3891 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3892 expect_messages->message, expect_messages->window, i);
3893 expect_messages = NULL;
3894 flush_events();
3896 SetForegroundWindow(GetDesktopWindow());
3897 ShowWindow(device_window, SW_MINIMIZE);
3898 ShowWindow(device_window, SW_RESTORE);
3899 ShowWindow(focus_window, SW_MINIMIZE);
3900 ShowWindow(focus_window, SW_RESTORE);
3901 SetForegroundWindow(focus_window);
3902 flush_events();
3904 /* Releasing a device in lost state breaks follow-up tests on native. */
3905 hr = reset_device(device, &device_desc);
3906 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3908 filter_messages = focus_window;
3910 ref = IDirect3DDevice9_Release(device);
3911 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3913 /* Fix up the mode until Wine's device release behavior is fixed. */
3914 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3915 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3917 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3918 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3919 (LONG_PTR)test_proc, proc, i);
3921 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3922 * on native in the test below. It isn't needed anyways. Creating the third
3923 * device will show it again. */
3924 filter_messages = NULL;
3925 ShowWindow(device_window, SW_HIDE);
3926 /* Remove the maximized state from the SYSCOMMAND test while we're not
3927 * interfering with a device. */
3928 ShowWindow(focus_window, SW_SHOWNORMAL);
3929 filter_messages = focus_window;
3931 device_desc.device_window = focus_window;
3932 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3934 skip("Failed to create a D3D device, skipping tests.\n");
3935 goto done;
3937 filter_messages = NULL;
3938 SetForegroundWindow(focus_window); /* For KDE. */
3939 flush_events();
3941 expect_messages = focus_loss_messages_filtered;
3942 windowposchanged_received = 0;
3943 SetForegroundWindow(GetDesktopWindow());
3944 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3945 expect_messages->message, expect_messages->window, i);
3946 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3947 expect_messages = NULL;
3949 /* The window is iconic even though no message was sent. */
3950 ok(!IsIconic(focus_window) == !tests[i].iconic,
3951 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
3953 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3954 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3956 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3957 ShowWindow(focus_window, SW_MINIMIZE);
3959 syscommand_received = 0;
3960 expect_messages = sc_restore_messages;
3961 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3962 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3963 expect_messages->message, expect_messages->window, i);
3964 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3965 expect_messages = NULL;
3966 flush_events();
3968 /* For FVWM. */
3969 ShowWindow(focus_window, SW_RESTORE);
3970 flush_events();
3972 expect_messages = sc_minimize_messages;
3973 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3974 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3975 expect_messages->message, expect_messages->window, i);
3976 expect_messages = NULL;
3977 flush_events();
3979 expect_messages = sc_maximize_messages;
3980 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3981 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3982 expect_messages->message, expect_messages->window, i);
3983 expect_messages = NULL;
3984 flush_events();
3986 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
3987 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
3988 SetForegroundWindow(GetDesktopWindow());
3989 flush_events();
3990 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
3991 flush_events();
3993 expect_messages = reactivate_messages_filtered;
3994 windowposchanged_received = 0;
3995 SetForegroundWindow(focus_window);
3996 flush_events();
3997 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3998 expect_messages->message, expect_messages->window, i);
3999 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
4000 ok(!windowposchanged_received || broken(1),
4001 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4002 expect_messages = NULL;
4004 filter_messages = focus_window;
4005 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4006 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
4008 hr = reset_device(device, &device_desc);
4009 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4011 ref = IDirect3DDevice9_Release(device);
4012 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4014 device_desc.device_window = device_window;
4015 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4017 skip("Failed to create a D3D device, skipping tests.\n");
4018 goto done;
4021 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
4022 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
4023 (LONG_PTR)test_proc, i);
4025 ref = IDirect3DDevice9_Release(device);
4026 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4028 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4029 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4030 (LONG_PTR)DefWindowProcA, proc, i);
4032 done:
4033 filter_messages = NULL;
4034 DestroyWindow(device_window);
4035 DestroyWindow(focus_window);
4036 SetEvent(thread_params.test_finished);
4037 WaitForSingleObject(thread, INFINITE);
4038 CloseHandle(thread);
4041 IDirect3D9_Release(d3d9);
4042 CloseHandle(thread_params.test_finished);
4043 CloseHandle(thread_params.window_created);
4044 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4047 static void test_wndproc_windowed(void)
4049 struct wndproc_thread_param thread_params;
4050 struct device_desc device_desc;
4051 IDirect3DDevice9 *device;
4052 WNDCLASSA wc = {0};
4053 IDirect3D9 *d3d9;
4054 HANDLE thread;
4055 LONG_PTR proc;
4056 HRESULT hr;
4057 ULONG ref;
4058 DWORD res, tid;
4059 HWND tmp;
4061 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4062 ok(!!d3d9, "Failed to create a D3D object.\n");
4064 wc.lpfnWndProc = test_proc;
4065 wc.lpszClassName = "d3d9_test_wndproc_wc";
4066 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4068 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4069 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4070 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4071 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4073 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4074 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4075 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4076 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4077 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4078 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4079 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4080 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4082 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4083 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4085 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4086 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4087 (LONG_PTR)test_proc, proc);
4088 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4089 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4090 (LONG_PTR)test_proc, proc);
4092 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4093 device_window, focus_window, thread_params.dummy_window);
4095 tmp = GetFocus();
4096 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4097 if (thread_params.running_in_foreground)
4099 tmp = GetForegroundWindow();
4100 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4101 thread_params.dummy_window, tmp);
4103 else
4104 skip("Not running in foreground, skip foreground window test\n");
4106 filter_messages = focus_window;
4108 device_desc.device_window = device_window;
4109 device_desc.width = 640;
4110 device_desc.height = 480;
4111 device_desc.flags = 0;
4112 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4114 skip("Failed to create a D3D device, skipping tests.\n");
4115 goto done;
4118 tmp = GetFocus();
4119 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4120 tmp = GetForegroundWindow();
4121 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4122 thread_params.dummy_window, tmp);
4124 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4125 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4126 (LONG_PTR)test_proc, proc);
4128 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4129 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4130 (LONG_PTR)test_proc, proc);
4132 filter_messages = NULL;
4134 device_desc.width = registry_mode.dmPelsWidth;
4135 device_desc.height = registry_mode.dmPelsHeight;
4136 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4137 hr = reset_device(device, &device_desc);
4138 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4140 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4141 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4142 (LONG_PTR)test_proc, proc);
4144 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4145 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4147 device_desc.flags = 0;
4148 hr = reset_device(device, &device_desc);
4149 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4151 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4152 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4153 (LONG_PTR)test_proc, proc);
4155 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4156 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4157 (LONG_PTR)test_proc, proc);
4159 filter_messages = focus_window;
4161 ref = IDirect3DDevice9_Release(device);
4162 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4164 filter_messages = device_window;
4166 device_desc.device_window = focus_window;
4167 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4169 skip("Failed to create a D3D device, skipping tests.\n");
4170 goto done;
4173 filter_messages = NULL;
4175 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4176 hr = reset_device(device, &device_desc);
4177 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4179 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4180 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4181 (LONG_PTR)test_proc, proc);
4183 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4184 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4186 device_desc.flags = 0;
4187 hr = reset_device(device, &device_desc);
4188 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4190 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4191 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4192 (LONG_PTR)test_proc, proc);
4194 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4195 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4196 (LONG_PTR)test_proc, proc);
4198 filter_messages = device_window;
4200 ref = IDirect3DDevice9_Release(device);
4201 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4203 device_desc.device_window = device_window;
4204 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4206 skip("Failed to create a D3D device, skipping tests.\n");
4207 goto done;
4210 filter_messages = NULL;
4212 device_desc.device_window = device_window;
4213 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4214 hr = reset_device(device, &device_desc);
4215 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4217 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4218 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4219 (LONG_PTR)test_proc, proc);
4221 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4222 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4224 device_desc.flags = 0;
4225 hr = reset_device(device, &device_desc);
4226 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4228 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4229 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4230 (LONG_PTR)test_proc, proc);
4232 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4233 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4234 (LONG_PTR)test_proc, proc);
4236 filter_messages = device_window;
4238 ref = IDirect3DDevice9_Release(device);
4239 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4241 done:
4242 filter_messages = NULL;
4243 IDirect3D9_Release(d3d9);
4245 SetEvent(thread_params.test_finished);
4246 WaitForSingleObject(thread, INFINITE);
4247 CloseHandle(thread_params.test_finished);
4248 CloseHandle(thread_params.window_created);
4249 CloseHandle(thread);
4251 DestroyWindow(device_window);
4252 DestroyWindow(focus_window);
4253 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4256 static void test_reset_fullscreen(void)
4258 struct device_desc device_desc;
4259 D3DDISPLAYMODE d3ddm, d3ddm2;
4260 unsigned int mode_count, i;
4261 IDirect3DDevice9 *device;
4262 WNDCLASSEXA wc = {0};
4263 IDirect3D9 *d3d;
4264 HRESULT hr;
4265 ATOM atom;
4266 static const struct message messages[] =
4268 /* Windows usually sends wparam = TRUE, except on the testbot,
4269 * where it randomly sends FALSE. Ignore it. */
4270 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4271 {0, 0, FALSE, 0},
4274 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4275 ok(!!d3d, "Failed to create a D3D object.\n");
4276 expect_messages = messages;
4278 wc.cbSize = sizeof(wc);
4279 wc.lpfnWndProc = test_proc;
4280 wc.lpszClassName = "test_reset_fullscreen";
4282 atom = RegisterClassExA(&wc);
4283 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4285 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4286 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4287 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4290 * Create a device in windowed mode.
4291 * Since the device is windowed and we haven't called any methods that
4292 * could show the window (such as ShowWindow or SetWindowPos) yet,
4293 * WM_ACTIVATEAPP will not have been sent.
4295 if (!(device = create_device(d3d, device_window, NULL)))
4297 skip("Unable to create device. Skipping test.\n");
4298 goto cleanup;
4302 * Switch to fullscreen mode.
4303 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4304 * message to be sent.
4306 device_desc.width = registry_mode.dmPelsWidth;
4307 device_desc.height = registry_mode.dmPelsHeight;
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(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4314 expect_messages = NULL;
4316 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
4317 mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
4318 for (i = 0; i < mode_count; ++i)
4320 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
4321 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4323 if (d3ddm2.Width != d3ddm.Width || d3ddm2.Height != d3ddm.Height)
4324 break;
4326 if (i == mode_count)
4328 skip("Could not find a suitable display mode.\n");
4329 goto cleanup;
4332 wm_size_received = 0;
4334 /* Fullscreen mode change. */
4335 device_desc.width = d3ddm2.Width;
4336 device_desc.height = d3ddm2.Height;
4337 device_desc.device_window = device_window;
4338 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4339 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4341 flush_events();
4342 ok(!wm_size_received, "Received unexpected WM_SIZE message.\n");
4344 cleanup:
4345 if (device) IDirect3DDevice9_Release(device);
4346 IDirect3D9_Release(d3d);
4347 DestroyWindow(device_window);
4348 device_window = focus_window = NULL;
4349 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4353 static inline void set_fpu_cw(WORD cw)
4355 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4356 #define D3D9_TEST_SET_FPU_CW 1
4357 __asm__ volatile ("fnclex");
4358 __asm__ volatile ("fldcw %0" : : "m" (cw));
4359 #elif defined(__i386__) && defined(_MSC_VER)
4360 #define D3D9_TEST_SET_FPU_CW 1
4361 __asm fnclex;
4362 __asm fldcw cw;
4363 #endif
4366 static inline WORD get_fpu_cw(void)
4368 WORD cw = 0;
4369 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4370 #define D3D9_TEST_GET_FPU_CW 1
4371 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4372 #elif defined(__i386__) && defined(_MSC_VER)
4373 #define D3D9_TEST_GET_FPU_CW 1
4374 __asm fnstcw cw;
4375 #endif
4376 return cw;
4379 static WORD callback_cw, callback_set_cw;
4380 static DWORD callback_tid;
4382 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4384 *out = NULL;
4385 return E_NOINTERFACE;
4388 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4390 callback_cw = get_fpu_cw();
4391 set_fpu_cw(callback_set_cw);
4392 callback_tid = GetCurrentThreadId();
4393 return 2;
4396 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4398 callback_cw = get_fpu_cw();
4399 set_fpu_cw(callback_set_cw);
4400 callback_tid = GetCurrentThreadId();
4401 return 1;
4404 static const IUnknownVtbl dummy_object_vtbl =
4406 dummy_object_QueryInterface,
4407 dummy_object_AddRef,
4408 dummy_object_Release,
4411 static const GUID d3d9_private_data_test_guid =
4413 0xfdb37466,
4414 0x428f,
4415 0x4edf,
4416 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4419 static void test_fpu_setup(void)
4421 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4422 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
4423 IUnknown dummy_object = {&dummy_object_vtbl};
4424 struct device_desc device_desc;
4425 IDirect3DSurface9 *surface;
4426 IDirect3DDevice9 *device;
4427 WORD cw, expected_cw;
4428 HWND window = NULL;
4429 IDirect3D9 *d3d9;
4430 HRESULT hr;
4432 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4433 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4434 ok(!!window, "Failed to create a window.\n");
4435 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4436 ok(!!d3d9, "Failed to create a D3D object.\n");
4438 device_desc.device_window = window;
4439 device_desc.width = 640;
4440 device_desc.height = 480;
4441 device_desc.flags = 0;
4443 set_fpu_cw(0xf60);
4444 cw = get_fpu_cw();
4445 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4447 if (!(device = create_device(d3d9, window, &device_desc)))
4449 skip("Failed to create a 3D device, skipping test.\n");
4450 set_fpu_cw(0x37f);
4451 goto done;
4454 expected_cw = is_64bit ? 0xf60 : 0x7f;
4456 cw = get_fpu_cw();
4457 todo_wine_if(is_64bit)
4458 ok(cw == expected_cw, "cw is %#x, expected %#x.\n", cw, expected_cw);
4460 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4461 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4463 callback_set_cw = 0xf60;
4464 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4465 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4466 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4467 todo_wine_if(is_64bit)
4468 ok(callback_cw == expected_cw, "Callback cw is %#x, expected %#x.\n", callback_cw, expected_cw);
4469 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4470 cw = get_fpu_cw();
4471 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4473 callback_cw = 0;
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");
4480 callback_set_cw = 0x7f;
4481 set_fpu_cw(0x7f);
4483 IDirect3DSurface9_Release(surface);
4485 callback_cw = 0;
4486 IDirect3DDevice9_Release(device);
4487 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4488 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4490 cw = get_fpu_cw();
4491 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4492 set_fpu_cw(0xf60);
4493 cw = get_fpu_cw();
4494 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4496 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4497 device = create_device(d3d9, window, &device_desc);
4498 ok(device != NULL, "CreateDevice failed.\n");
4500 cw = get_fpu_cw();
4501 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4503 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4504 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4506 callback_cw = 0;
4507 callback_set_cw = 0x37f;
4508 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4509 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4510 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4511 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4512 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4513 cw = get_fpu_cw();
4514 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4516 IDirect3DSurface9_Release(surface);
4518 callback_cw = 0;
4519 IDirect3DDevice9_Release(device);
4520 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4521 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4523 done:
4524 IDirect3D9_Release(d3d9);
4525 DestroyWindow(window);
4526 #endif
4529 static void test_window_style(void)
4531 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4532 LONG device_style, device_exstyle;
4533 LONG focus_style, focus_exstyle;
4534 struct device_desc device_desc;
4535 LONG style, expected_style;
4536 IDirect3DDevice9 *device;
4537 IDirect3D9 *d3d9;
4538 HRESULT hr;
4539 ULONG ref;
4540 BOOL ret;
4541 static const struct
4543 DWORD device_flags;
4544 LONG style, focus_loss_style, exstyle;
4546 tests[] =
4548 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4549 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4551 unsigned int i;
4553 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4554 ok(!!d3d9, "Failed to create a D3D object.\n");
4555 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4557 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4559 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4560 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4561 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4562 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4564 device_style = GetWindowLongA(device_window, GWL_STYLE);
4565 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4566 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4567 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4569 GetWindowRect(focus_window, &focus_rect);
4570 GetWindowRect(device_window, &device_rect);
4572 device_desc.device_window = device_window;
4573 device_desc.width = registry_mode.dmPelsWidth;
4574 device_desc.height = registry_mode.dmPelsHeight;
4575 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4576 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4578 skip("Failed to create a D3D device, skipping tests.\n");
4579 DestroyWindow(device_window);
4580 DestroyWindow(focus_window);
4581 break;
4584 style = GetWindowLongA(device_window, GWL_STYLE);
4585 expected_style = device_style | tests[i].style;
4586 todo_wine 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 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4591 expected_style, style, i);
4593 style = GetWindowLongA(focus_window, GWL_STYLE);
4594 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4595 focus_style, style, i);
4596 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4597 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4598 focus_exstyle, style, i);
4600 GetWindowRect(device_window, &r);
4601 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4602 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4603 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4604 else
4605 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4606 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4607 GetClientRect(device_window, &r2);
4608 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4609 GetWindowRect(focus_window, &r);
4610 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4611 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4613 device_desc.flags = 0;
4614 hr = reset_device(device, &device_desc);
4615 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4617 style = GetWindowLongA(device_window, GWL_STYLE);
4618 expected_style = device_style | tests[i].style;
4619 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4620 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4621 expected_style, style, i);
4622 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4623 expected_style = device_exstyle | tests[i].exstyle;
4624 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4625 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4626 expected_style, style, i);
4628 style = GetWindowLongA(focus_window, GWL_STYLE);
4629 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4630 focus_style, style, i);
4631 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4632 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4633 focus_exstyle, style, i);
4635 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4636 hr = reset_device(device, &device_desc);
4637 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4638 ret = SetForegroundWindow(GetDesktopWindow());
4639 ok(ret, "Failed to set foreground window.\n");
4641 style = GetWindowLongA(device_window, GWL_STYLE);
4642 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4643 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4644 expected_style, style);
4645 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4646 expected_style = device_exstyle | tests[i].exstyle;
4647 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4648 expected_style, style);
4650 style = GetWindowLongA(focus_window, GWL_STYLE);
4651 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4652 focus_style, style);
4653 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4654 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4655 focus_exstyle, style);
4657 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4658 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4659 * like a good idea to reset it first. */
4660 ShowWindow(focus_window, SW_MINIMIZE);
4661 ShowWindow(focus_window, SW_RESTORE);
4662 ret = SetForegroundWindow(focus_window);
4663 ok(ret, "Failed to set foreground window.\n");
4664 flush_events();
4665 hr = reset_device(device, &device_desc);
4666 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4668 ref = IDirect3DDevice9_Release(device);
4669 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4671 DestroyWindow(device_window);
4672 DestroyWindow(focus_window);
4674 IDirect3D9_Release(d3d9);
4677 static const POINT *expect_pos;
4679 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4681 if (message == WM_MOUSEMOVE)
4683 if (expect_pos && expect_pos->x && expect_pos->y)
4685 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4687 ClientToScreen(window, &p);
4688 if (expect_pos->x == p.x && expect_pos->y == p.y)
4689 ++expect_pos;
4693 return DefWindowProcA(window, message, wparam, lparam);
4696 static void test_cursor_pos(void)
4698 IDirect3DSurface9 *cursor;
4699 IDirect3DDevice9 *device;
4700 WNDCLASSA wc = {0};
4701 IDirect3D9 *d3d9;
4702 UINT refcount;
4703 HWND window;
4704 HRESULT hr;
4705 BOOL ret;
4707 /* Note that we don't check for movement we're not supposed to receive.
4708 * That's because it's hard to distinguish from the user accidentally
4709 * moving the mouse. */
4710 static const POINT points[] =
4712 {50, 50},
4713 {75, 75},
4714 {100, 100},
4715 {125, 125},
4716 {150, 150},
4717 {125, 125},
4718 {150, 150},
4719 {150, 150},
4720 {0, 0},
4723 wc.lpfnWndProc = test_cursor_proc;
4724 wc.lpszClassName = "d3d9_test_cursor_wc";
4725 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4726 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4727 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4728 ShowWindow(window, SW_SHOW);
4729 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4730 ok(!!d3d9, "Failed to create a D3D object.\n");
4732 device = create_device(d3d9, window, NULL);
4733 if (!device)
4735 skip("Failed to create a D3D device, skipping tests.\n");
4736 goto done;
4739 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4740 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4741 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4742 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4743 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4744 IDirect3DSurface9_Release(cursor);
4745 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4746 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4748 flush_events();
4749 expect_pos = points;
4751 ret = SetCursorPos(50, 50);
4752 ok(ret, "Failed to set cursor position.\n");
4753 flush_events();
4755 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4756 flush_events();
4757 /* SetCursorPosition() eats duplicates. */
4758 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4759 flush_events();
4761 ret = SetCursorPos(100, 100);
4762 ok(ret, "Failed to set cursor position.\n");
4763 flush_events();
4764 /* Even if the position was set with SetCursorPos(). */
4765 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4766 flush_events();
4768 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4769 flush_events();
4770 ret = SetCursorPos(150, 150);
4771 ok(ret, "Failed to set cursor position.\n");
4772 flush_events();
4773 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4774 flush_events();
4776 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4777 flush_events();
4778 /* SetCursorPos() doesn't. */
4779 ret = SetCursorPos(150, 150);
4780 ok(ret, "Failed to set cursor position.\n");
4781 flush_events();
4783 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4784 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4786 refcount = IDirect3DDevice9_Release(device);
4787 ok(!refcount, "Device has %u references left.\n", refcount);
4788 done:
4789 DestroyWindow(window);
4790 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4791 IDirect3D9_Release(d3d9);
4794 static void test_mode_change(void)
4796 RECT d3d_rect, focus_rect, r;
4797 struct device_desc device_desc;
4798 IDirect3DSurface9 *backbuffer;
4799 IDirect3DDevice9 *device;
4800 D3DSURFACE_DESC desc;
4801 IDirect3D9 *d3d9;
4802 DEVMODEW devmode;
4803 ULONG refcount;
4804 UINT adapter_mode_count, i;
4805 HRESULT hr;
4806 DWORD ret;
4807 LONG change_ret;
4808 D3DDISPLAYMODE d3ddm;
4809 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4811 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4812 ok(!!d3d9, "Failed to create a D3D object.\n");
4814 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4815 for (i = 0; i < adapter_mode_count; ++i)
4817 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4818 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4820 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4821 continue;
4822 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4823 * refuses to create a device at these sizes. */
4824 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4825 continue;
4827 if (!user32_width)
4829 user32_width = d3ddm.Width;
4830 user32_height = d3ddm.Height;
4831 continue;
4834 /* Make sure the d3d mode is smaller in width or height and at most
4835 * equal in the other dimension than the mode passed to
4836 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4837 * the ChangeDisplaySettings parameters + 12. */
4838 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4839 continue;
4840 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4842 d3d_width = d3ddm.Width;
4843 d3d_height = d3ddm.Height;
4844 break;
4846 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4848 d3d_width = user32_width;
4849 d3d_height = user32_height;
4850 user32_width = d3ddm.Width;
4851 user32_height = d3ddm.Height;
4852 break;
4856 if (!d3d_width)
4858 skip("Could not find adequate modes, skipping mode tests.\n");
4859 IDirect3D9_Release(d3d9);
4860 return;
4863 memset(&devmode, 0, sizeof(devmode));
4864 devmode.dmSize = sizeof(devmode);
4865 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4866 devmode.dmPelsWidth = user32_width;
4867 devmode.dmPelsHeight = user32_height;
4868 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4869 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4871 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4872 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4873 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4874 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4876 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4877 GetWindowRect(focus_window, &focus_rect);
4879 device_desc.device_window = device_window;
4880 device_desc.width = d3d_width;
4881 device_desc.height = d3d_height;
4882 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4883 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4885 skip("Failed to create a D3D device, skipping tests.\n");
4886 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4887 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4888 goto done;
4891 devmode.dmPelsWidth = user32_width;
4892 devmode.dmPelsHeight = user32_height;
4893 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4894 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4896 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4897 ok(ret, "Failed to get display mode.\n");
4898 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4899 "Expected resolution %ux%u, got %ux%u.\n",
4900 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4902 GetWindowRect(device_window, &r);
4903 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
4904 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
4905 GetWindowRect(focus_window, &r);
4906 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
4907 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
4909 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4910 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
4911 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
4912 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
4913 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4914 desc.Width, d3d_width);
4915 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4916 desc.Height, d3d_height);
4917 IDirect3DSurface9_Release(backbuffer);
4919 refcount = IDirect3DDevice9_Release(device);
4920 ok(!refcount, "Device has %u references left.\n", refcount);
4922 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4923 ok(ret, "Failed to get display mode.\n");
4924 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4925 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4926 "Expected resolution %ux%u, got %ux%u.\n",
4927 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4929 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4930 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4932 /* The mode restore also happens when the device was created at the original screen size. */
4934 device_desc.device_window = device_window;
4935 device_desc.width = registry_mode.dmPelsWidth;
4936 device_desc.height = registry_mode.dmPelsHeight;
4937 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4938 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4940 devmode.dmPelsWidth = user32_width;
4941 devmode.dmPelsHeight = user32_height;
4942 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4943 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4945 refcount = IDirect3DDevice9_Release(device);
4946 ok(!refcount, "Device has %u references left.\n", refcount);
4948 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4949 ok(ret, "Failed to get display mode.\n");
4950 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4951 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4952 "Expected resolution %ux%u, got %ux%u.\n",
4953 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4955 done:
4956 DestroyWindow(device_window);
4957 DestroyWindow(focus_window);
4958 IDirect3D9_Release(d3d9);
4961 static void test_device_window_reset(void)
4963 RECT fullscreen_rect, device_rect, r;
4964 struct device_desc device_desc;
4965 IDirect3DDevice9 *device;
4966 WNDCLASSA wc = {0};
4967 IDirect3D9 *d3d9;
4968 LONG_PTR proc;
4969 HRESULT hr;
4970 ULONG ref;
4972 wc.lpfnWndProc = test_proc;
4973 wc.lpszClassName = "d3d9_test_wndproc_wc";
4974 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4976 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4977 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4978 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4979 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4980 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4981 ok(!!d3d9, "Failed to create a D3D object.\n");
4983 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4984 GetWindowRect(device_window, &device_rect);
4986 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4987 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4988 (LONG_PTR)test_proc, proc);
4989 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4990 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4991 (LONG_PTR)test_proc, proc);
4993 device_desc.device_window = NULL;
4994 device_desc.width = registry_mode.dmPelsWidth;
4995 device_desc.height = registry_mode.dmPelsHeight;
4996 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4997 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4999 skip("Failed to create a D3D device, skipping tests.\n");
5000 goto done;
5003 GetWindowRect(focus_window, &r);
5004 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5005 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5006 GetWindowRect(device_window, &r);
5007 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
5008 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
5010 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5011 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5012 (LONG_PTR)test_proc, proc);
5013 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5014 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5016 device_desc.device_window = device_window;
5017 hr = reset_device(device, &device_desc);
5018 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5020 GetWindowRect(focus_window, &r);
5021 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5022 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5023 GetWindowRect(device_window, &r);
5024 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5025 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5027 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5028 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5029 (LONG_PTR)test_proc, proc);
5030 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5031 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5033 ref = IDirect3DDevice9_Release(device);
5034 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5036 done:
5037 IDirect3D9_Release(d3d9);
5038 DestroyWindow(device_window);
5039 DestroyWindow(focus_window);
5040 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
5043 static void test_reset_resources(void)
5045 IDirect3DSurface9 *surface, *rt;
5046 IDirect3DTexture9 *texture;
5047 IDirect3DDevice9 *device;
5048 IDirect3D9 *d3d9;
5049 unsigned int i;
5050 D3DCAPS9 caps;
5051 HWND window;
5052 HRESULT hr;
5053 ULONG ref;
5055 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5056 0, 0, 640, 480, 0, 0, 0, 0);
5057 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5058 ok(!!d3d9, "Failed to create a D3D object.\n");
5060 if (!(device = create_device(d3d9, window, NULL)))
5062 skip("Failed to create a D3D device, skipping tests.\n");
5063 goto done;
5066 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5067 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5069 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5070 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5071 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5072 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5073 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5074 IDirect3DSurface9_Release(surface);
5076 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5078 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5079 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5080 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5081 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5082 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5083 IDirect3DTexture9_Release(texture);
5084 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5085 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5086 IDirect3DSurface9_Release(surface);
5089 hr = reset_device(device, NULL);
5090 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5092 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5093 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5094 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5095 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5096 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5097 IDirect3DSurface9_Release(surface);
5098 IDirect3DSurface9_Release(rt);
5100 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5102 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5103 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5106 ref = IDirect3DDevice9_Release(device);
5107 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5109 done:
5110 IDirect3D9_Release(d3d9);
5111 DestroyWindow(window);
5114 static void test_set_rt_vp_scissor(void)
5116 IDirect3DStateBlock9 *stateblock;
5117 IDirect3DDevice9 *device;
5118 IDirect3DSurface9 *rt;
5119 IDirect3D9 *d3d9;
5120 D3DVIEWPORT9 vp;
5121 UINT refcount;
5122 HWND window;
5123 HRESULT hr;
5124 RECT rect;
5126 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5127 0, 0, 640, 480, 0, 0, 0, 0);
5128 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5129 ok(!!d3d9, "Failed to create a D3D object.\n");
5130 if (!(device = create_device(d3d9, window, NULL)))
5132 skip("Failed to create a D3D device, skipping tests.\n");
5133 DestroyWindow(window);
5134 return;
5137 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5138 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5139 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5141 hr = IDirect3DDevice9_GetViewport(device, &vp);
5142 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5143 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5144 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5145 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5146 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5147 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5148 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5150 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5151 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5152 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5153 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5155 hr = IDirect3DDevice9_BeginStateBlock(device);
5156 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5158 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5159 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5161 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5162 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5163 IDirect3DStateBlock9_Release(stateblock);
5165 hr = IDirect3DDevice9_GetViewport(device, &vp);
5166 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5167 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5168 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5169 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5170 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5171 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5172 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5174 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5175 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5176 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5177 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5179 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5180 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5182 vp.X = 10;
5183 vp.Y = 20;
5184 vp.Width = 30;
5185 vp.Height = 40;
5186 vp.MinZ = 0.25f;
5187 vp.MaxZ = 0.75f;
5188 hr = IDirect3DDevice9_SetViewport(device, &vp);
5189 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5191 SetRect(&rect, 50, 60, 70, 80);
5192 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5193 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5195 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5196 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5198 hr = IDirect3DDevice9_GetViewport(device, &vp);
5199 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5200 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5201 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5202 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5203 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5204 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5205 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5207 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5208 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5209 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5210 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5212 IDirect3DSurface9_Release(rt);
5213 refcount = IDirect3DDevice9_Release(device);
5214 ok(!refcount, "Device has %u references left.\n", refcount);
5215 IDirect3D9_Release(d3d9);
5216 DestroyWindow(window);
5219 static void test_volume_get_container(void)
5221 IDirect3DVolumeTexture9 *texture = NULL;
5222 IDirect3DVolume9 *volume = NULL;
5223 IDirect3DDevice9 *device;
5224 IUnknown *container;
5225 IDirect3D9 *d3d9;
5226 ULONG refcount;
5227 D3DCAPS9 caps;
5228 HWND window;
5229 HRESULT hr;
5231 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5232 0, 0, 640, 480, 0, 0, 0, 0);
5233 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5234 ok(!!d3d9, "Failed to create a D3D object.\n");
5235 if (!(device = create_device(d3d9, window, NULL)))
5237 skip("Failed to create a D3D device, skipping tests.\n");
5238 IDirect3D9_Release(d3d9);
5239 DestroyWindow(window);
5240 return;
5243 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5244 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5245 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5247 skip("No volume texture support, skipping tests.\n");
5248 IDirect3DDevice9_Release(device);
5249 IDirect3D9_Release(d3d9);
5250 DestroyWindow(window);
5251 return;
5254 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5255 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5256 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5257 ok(!!texture, "Got unexpected texture %p.\n", texture);
5259 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5260 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5261 ok(!!volume, "Got unexpected volume %p.\n", volume);
5263 /* These should work... */
5264 container = NULL;
5265 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5266 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5267 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5268 IUnknown_Release(container);
5270 container = NULL;
5271 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5272 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5273 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5274 IUnknown_Release(container);
5276 container = NULL;
5277 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5278 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5279 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5280 IUnknown_Release(container);
5282 container = NULL;
5283 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5284 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5285 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5286 IUnknown_Release(container);
5288 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5289 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5290 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5291 ok(!container, "Got unexpected container %p.\n", container);
5293 IDirect3DVolume9_Release(volume);
5294 IDirect3DVolumeTexture9_Release(texture);
5295 refcount = IDirect3DDevice9_Release(device);
5296 ok(!refcount, "Device has %u references left.\n", refcount);
5297 IDirect3D9_Release(d3d9);
5298 DestroyWindow(window);
5301 static void test_volume_resource(void)
5303 IDirect3DVolumeTexture9 *texture;
5304 IDirect3DResource9 *resource;
5305 IDirect3DVolume9 *volume;
5306 IDirect3DDevice9 *device;
5307 IDirect3D9 *d3d9;
5308 ULONG refcount;
5309 D3DCAPS9 caps;
5310 HWND window;
5311 HRESULT hr;
5313 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5314 0, 0, 640, 480, 0, 0, 0, 0);
5315 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5316 ok(!!d3d9, "Failed to create a D3D object.\n");
5317 if (!(device = create_device(d3d9, window, NULL)))
5319 skip("Failed to create a D3D device, skipping tests.\n");
5320 IDirect3D9_Release(d3d9);
5321 DestroyWindow(window);
5322 return;
5325 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5326 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5327 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5329 skip("No volume texture support, skipping tests.\n");
5330 IDirect3DDevice9_Release(device);
5331 IDirect3D9_Release(d3d9);
5332 DestroyWindow(window);
5333 return;
5336 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5337 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5338 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5339 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5340 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5341 IDirect3DVolumeTexture9_Release(texture);
5343 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5344 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5346 IDirect3DVolume9_Release(volume);
5347 refcount = IDirect3DDevice9_Release(device);
5348 ok(!refcount, "Device has %u references left.\n", refcount);
5349 IDirect3D9_Release(d3d9);
5350 DestroyWindow(window);
5353 static void test_vb_lock_flags(void)
5355 static const struct
5357 DWORD flags;
5358 const char *debug_string;
5359 HRESULT win7_result;
5361 test_data[] =
5363 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5364 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5365 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5366 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5367 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5368 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5369 /* Completely bogus flags aren't an error. */
5370 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5372 IDirect3DVertexBuffer9 *buffer;
5373 IDirect3DDevice9 *device;
5374 IDirect3D9 *d3d9;
5375 unsigned int i;
5376 ULONG refcount;
5377 HWND window;
5378 HRESULT hr;
5379 void *data;
5381 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5382 0, 0, 640, 480, 0, 0, 0, 0);
5383 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5384 ok(!!d3d9, "Failed to create a D3D object.\n");
5385 if (!(device = create_device(d3d9, window, NULL)))
5387 skip("Failed to create a D3D device, skipping tests.\n");
5388 IDirect3D9_Release(d3d9);
5389 DestroyWindow(window);
5390 return;
5393 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5394 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5396 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5398 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5399 /* Windows XP always returns D3D_OK even with flags that don't make
5400 * sense. Windows 7 returns an error. At least one game (Shaiya)
5401 * depends on the Windows XP result, so mark the Windows 7 behavior as
5402 * broken. */
5403 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5404 hr, test_data[i].debug_string);
5405 if (SUCCEEDED(hr))
5407 ok(!!data, "Got unexpected data %p.\n", data);
5408 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5409 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5413 IDirect3DVertexBuffer9_Release(buffer);
5414 refcount = IDirect3DDevice9_Release(device);
5415 ok(!refcount, "Device has %u references left.\n", refcount);
5416 IDirect3D9_Release(d3d9);
5417 DestroyWindow(window);
5420 static const char *debug_d3dpool(D3DPOOL pool)
5422 switch (pool)
5424 case D3DPOOL_DEFAULT:
5425 return "D3DPOOL_DEFAULT";
5426 case D3DPOOL_SYSTEMMEM:
5427 return "D3DPOOL_SYSTEMMEM";
5428 case D3DPOOL_SCRATCH:
5429 return "D3DPOOL_SCRATCH";
5430 case D3DPOOL_MANAGED:
5431 return "D3DPOOL_MANAGED";
5432 default:
5433 return "unknown pool";
5437 static void test_vertex_buffer_alignment(void)
5439 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5440 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5441 IDirect3DVertexBuffer9 *buffer = NULL;
5442 const unsigned int align = 16;
5443 IDirect3DDevice9 *device;
5444 unsigned int i, j;
5445 IDirect3D9 *d3d9;
5446 ULONG refcount;
5447 HWND window;
5448 HRESULT hr;
5449 void *data;
5451 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5452 0, 0, 640, 480, 0, 0, 0, 0);
5453 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5454 ok(!!d3d9, "Failed to create a D3D object.\n");
5455 if (!(device = create_device(d3d9, window, NULL)))
5457 skip("Failed to create a D3D device, skipping tests.\n");
5458 IDirect3D9_Release(d3d9);
5459 DestroyWindow(window);
5460 return;
5463 for (i = 0; i < ARRAY_SIZE(sizes); ++i)
5465 for (j = 0; j < ARRAY_SIZE(pools); ++j)
5467 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5468 if (pools[j] == D3DPOOL_SCRATCH)
5469 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5470 else
5471 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5472 debug_d3dpool(pools[j]), sizes[i], hr);
5473 if (FAILED(hr))
5474 continue;
5476 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5477 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5478 ok(!((DWORD_PTR)data & (align - 1)),
5479 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5480 data, align, sizes[i], debug_d3dpool(pools[j]));
5481 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5482 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5483 IDirect3DVertexBuffer9_Release(buffer);
5487 refcount = IDirect3DDevice9_Release(device);
5488 ok(!refcount, "Device has %u references left.\n", refcount);
5489 IDirect3D9_Release(d3d9);
5490 DestroyWindow(window);
5493 static void test_query_support(void)
5495 static const D3DQUERYTYPE queries[] =
5497 D3DQUERYTYPE_VCACHE,
5498 D3DQUERYTYPE_RESOURCEMANAGER,
5499 D3DQUERYTYPE_VERTEXSTATS,
5500 D3DQUERYTYPE_EVENT,
5501 D3DQUERYTYPE_OCCLUSION,
5502 D3DQUERYTYPE_TIMESTAMP,
5503 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5504 D3DQUERYTYPE_TIMESTAMPFREQ,
5505 D3DQUERYTYPE_PIPELINETIMINGS,
5506 D3DQUERYTYPE_INTERFACETIMINGS,
5507 D3DQUERYTYPE_VERTEXTIMINGS,
5508 D3DQUERYTYPE_PIXELTIMINGS,
5509 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5510 D3DQUERYTYPE_CACHEUTILIZATION,
5512 IDirect3DQuery9 *query = NULL;
5513 IDirect3DDevice9 *device;
5514 IDirect3D9 *d3d9;
5515 unsigned int i;
5516 ULONG refcount;
5517 BOOL supported;
5518 HWND window;
5519 HRESULT hr;
5521 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5522 0, 0, 640, 480, 0, 0, 0, 0);
5523 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5524 ok(!!d3d9, "Failed to create a D3D object.\n");
5525 if (!(device = create_device(d3d9, window, NULL)))
5527 skip("Failed to create a D3D device, skipping tests.\n");
5528 IDirect3D9_Release(d3d9);
5529 DestroyWindow(window);
5530 return;
5533 for (i = 0; i < ARRAY_SIZE(queries); ++i)
5535 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5536 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5538 supported = hr == D3D_OK;
5540 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5541 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5543 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5544 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5546 if (query)
5548 IDirect3DQuery9_Release(query);
5549 query = NULL;
5553 for (i = 0; i < 40; ++i)
5555 if (D3DQUERYTYPE_VCACHE <= i && i <= D3DQUERYTYPE_MEMORYPRESSURE)
5556 continue;
5558 hr = IDirect3DDevice9_CreateQuery(device, i, NULL);
5559 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5561 query = (IDirect3DQuery9 *)0xdeadbeef;
5562 hr = IDirect3DDevice9_CreateQuery(device, i, &query);
5563 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5564 ok(query == (IDirect3DQuery9 *)0xdeadbeef, "Got unexpected query %p.\n", query);
5567 refcount = IDirect3DDevice9_Release(device);
5568 ok(!refcount, "Device has %u references left.\n", refcount);
5569 IDirect3D9_Release(d3d9);
5570 DestroyWindow(window);
5573 static void test_occlusion_query(void)
5575 static const float quad[] =
5577 -1.0f, -1.0f, 0.0f,
5578 -1.0f, 1.0f, 0.0f,
5579 1.0f, 1.0f, 0.0f,
5580 1.0f, -1.0f, 0.0f,
5582 unsigned int data_size, i, count;
5583 struct device_desc device_desc;
5584 IDirect3DQuery9 *query = NULL;
5585 IDirect3DDevice9 *device;
5586 IDirect3DSurface9 *rt;
5587 IDirect3D9 *d3d9;
5588 D3DVIEWPORT9 vp;
5589 ULONG refcount;
5590 D3DCAPS9 caps;
5591 HWND window;
5592 HRESULT hr;
5593 union
5595 WORD word[4];
5596 DWORD dword[2];
5597 UINT64 uint;
5598 } data, expected;
5599 BOOL broken_occlusion = FALSE;
5600 expected.uint = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5602 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5603 0, 0, 640, 480, 0, 0, 0, 0);
5604 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5605 ok(!!d3d9, "Failed to create a D3D object.\n");
5606 device_desc.device_window = window;
5607 device_desc.width = registry_mode.dmPelsWidth;
5608 device_desc.height = registry_mode.dmPelsHeight;
5609 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5610 if (!(device = create_device(d3d9, window, &device_desc)))
5612 skip("Failed to create a D3D device, skipping tests.\n");
5613 IDirect3D9_Release(d3d9);
5614 DestroyWindow(window);
5615 return;
5618 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5619 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5620 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5621 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5622 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5623 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5625 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5626 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5627 if (!query)
5629 skip("Occlusion queries are not supported, skipping tests.\n");
5630 IDirect3DDevice9_Release(device);
5631 IDirect3D9_Release(d3d9);
5632 DestroyWindow(window);
5633 return;
5636 data_size = IDirect3DQuery9_GetDataSize(query);
5637 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5639 memset(&data, 0xff, sizeof(data));
5640 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5641 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5642 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5643 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5644 ok(data.dword[0] == 0xdddddddd && data.dword[1] == 0xffffffff,
5645 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5647 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5648 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5649 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5650 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5651 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5652 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5654 data.dword[0] = 0x12345678;
5655 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5656 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5657 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5658 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5659 if (hr == D3D_OK)
5660 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5662 hr = IDirect3DDevice9_BeginScene(device);
5663 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5664 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5665 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5666 hr = IDirect3DDevice9_EndScene(device);
5667 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5669 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5670 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5671 for (i = 0; i < 500; ++i)
5673 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5674 break;
5675 Sleep(10);
5677 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5679 memset(&data, 0xff, sizeof(data));
5680 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5681 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5682 ok(data.dword[0] == expected.dword[0] || broken(!data.dword[0]),
5683 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5684 if (!data.dword[0])
5686 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5687 broken_occlusion = TRUE;
5690 memset(&data, 0xff, sizeof(data));
5691 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5692 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5693 if (!broken_occlusion)
5694 ok(data.word[0] == expected.word[0],
5695 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5696 ok(data.word[1] == 0xffff,
5697 "Data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5699 memset(&data, 0xf0, sizeof(data));
5700 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5701 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5702 if (!broken_occlusion)
5703 ok(data.dword[0] == expected.dword[0],
5704 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5705 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5706 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5707 on AMD and Nvidia respectively). */
5708 if (0)
5710 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5711 data.dword[1]);
5714 memset(&data, 0xff, sizeof(data));
5715 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5716 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5717 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5719 /* This crashes on Windows. */
5720 if (0)
5722 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5723 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5726 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5727 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5728 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5729 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5730 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5731 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5733 if (broken_occlusion)
5734 goto done;
5736 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5737 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5739 vp.X = 0;
5740 vp.Y = 0;
5741 vp.Width = min(caps.MaxTextureWidth, 8192);
5742 vp.Height = min(caps.MaxTextureHeight, 8192);
5743 vp.MinZ = 0.0f;
5744 vp.MaxZ = 1.0f;
5745 hr = IDirect3DDevice9_SetViewport(device, &vp);
5746 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5748 hr = IDirect3DDevice9_CreateRenderTarget(device, vp.Width, vp.Height,
5749 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5750 if (FAILED(hr))
5752 skip("Failed to create render target (width %u, height %u), hr %#x.\n", vp.Width, vp.Height, hr);
5753 goto done;
5755 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5756 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5757 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5758 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
5759 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5761 expected.uint = vp.Width * vp.Height;
5762 count = ((((UINT64)~0u) + 1) / expected.uint) + 1;
5763 expected.uint *= count;
5765 trace("Expects 0x%08x%08x samples.\n", expected.dword[1], expected.dword[0]);
5767 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5768 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5769 hr = IDirect3DDevice9_BeginScene(device);
5770 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5771 for (i = 0; i < count; i++)
5773 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5774 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5776 hr = IDirect3DDevice9_EndScene(device);
5777 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5778 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5779 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5781 for (i = 0; i < 500; ++i)
5783 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5784 break;
5785 Sleep(10);
5787 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5789 memset(&data, 0xff, sizeof(data));
5790 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5791 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5792 ok((data.dword[0] == expected.dword[0] && data.dword[1] == expected.dword[1])
5793 || (data.dword[0] == 0xffffffff && !data.dword[1])
5794 || broken(data.dword[0] < 0xffffffff && !data.dword[1]),
5795 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5797 IDirect3DSurface9_Release(rt);
5799 done:
5800 IDirect3DQuery9_Release(query);
5801 refcount = IDirect3DDevice9_Release(device);
5802 ok(!refcount, "Device has %u references left.\n", refcount);
5803 IDirect3D9_Release(d3d9);
5804 DestroyWindow(window);
5807 static void test_timestamp_query(void)
5809 static const float quad[] =
5811 -1.0f, -1.0f, 0.0f,
5812 -1.0f, 1.0f, 0.0f,
5813 1.0f, 1.0f, 0.0f,
5814 1.0f, -1.0f, 0.0f,
5816 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5817 unsigned int data_size, i;
5818 IDirect3DDevice9 *device;
5819 IDirect3D9 *d3d9;
5820 ULONG refcount;
5821 HWND window;
5822 HRESULT hr;
5823 DWORD timestamp[2], freq[2];
5824 WORD disjoint[2];
5826 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5827 0, 0, 640, 480, 0, 0, 0, 0);
5828 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5829 ok(!!d3d9, "Failed to create a D3D object.\n");
5830 if (!(device = create_device(d3d9, window, NULL)))
5832 skip("Failed to create a D3D device, skipping tests.\n");
5833 IDirect3D9_Release(d3d9);
5834 DestroyWindow(window);
5835 return;
5838 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5839 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5840 if (FAILED(hr))
5842 skip("Timestamp queries are not supported, skipping tests.\n");
5843 IDirect3DDevice9_Release(device);
5844 IDirect3D9_Release(d3d9);
5845 DestroyWindow(window);
5846 return;
5848 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5849 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5851 memset(freq, 0xff, sizeof(freq));
5852 hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH);
5853 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5854 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5855 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5856 ok(freq[0] == 0xdddddddd && freq[1] == 0xffffffff,
5857 "Got unexpected query result 0x%08x%08x.\n", freq[1], freq[0]);
5859 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5860 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5861 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5862 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5864 memset(disjoint, 0xff, sizeof(disjoint));
5865 hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH);
5866 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5867 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5868 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5869 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xffff,
5870 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
5871 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(DWORD), D3DGETDATA_FLUSH);
5872 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5873 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xdddd,
5874 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
5876 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
5877 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5878 data_size = IDirect3DQuery9_GetDataSize(query);
5879 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5881 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
5882 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5883 for (i = 0; i < 500; ++i)
5885 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5886 break;
5887 Sleep(10);
5889 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5891 memset(freq, 0xff, sizeof(freq));
5892 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5893 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5894 ok(freq[1] == 0xffffffff,
5895 "Freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
5896 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
5897 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5898 ok(freq[1] != 0xffffffff, "High bytes of freq were not modified (0x%.8x).\n",
5899 freq[1]);
5901 memset(timestamp, 0xff, sizeof(timestamp));
5902 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5903 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5904 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5905 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5906 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xffffffff,
5907 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
5908 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5909 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5910 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xdddddddd,
5911 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
5913 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5914 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5915 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5916 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5917 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5918 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5920 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5921 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5923 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5924 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5925 hr = IDirect3DDevice9_BeginScene(device);
5926 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5927 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5928 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5929 hr = IDirect3DDevice9_EndScene(device);
5930 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5932 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5933 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5934 for (i = 0; i < 500; ++i)
5936 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5937 break;
5938 Sleep(10);
5940 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5942 memset(timestamp, 0xff, sizeof(timestamp));
5943 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5944 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5945 ok(timestamp[1] == 0xffffffff,
5946 "Timestamp was modified outside of the expected size (0x%.8x).\n",
5947 timestamp[1]);
5949 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5950 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5951 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5952 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5953 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5954 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5956 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5957 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5958 for (i = 0; i < 500; ++i)
5960 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5961 break;
5962 Sleep(10);
5964 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5966 memset(disjoint, 0xff, sizeof(disjoint));
5967 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5968 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5969 ok(disjoint[1] == 0xffff,
5970 "Disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
5971 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
5972 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5973 ok(disjoint[1] != 0xffff, "High bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
5975 /* It's not strictly necessary for the TIMESTAMP query to be inside
5976 * a TIMESTAMP_DISJOINT query. */
5977 hr = IDirect3DDevice9_BeginScene(device);
5978 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5979 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5980 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5981 hr = IDirect3DDevice9_EndScene(device);
5982 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5984 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5985 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5986 for (i = 0; i < 500; ++i)
5988 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5989 break;
5990 Sleep(10);
5992 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5993 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5994 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5996 IDirect3DQuery9_Release(query);
5997 IDirect3DQuery9_Release(disjoint_query);
5998 IDirect3DQuery9_Release(freq_query);
5999 refcount = IDirect3DDevice9_Release(device);
6000 ok(!refcount, "Device has %u references left.\n", refcount);
6001 IDirect3D9_Release(d3d9);
6002 DestroyWindow(window);
6005 static void test_get_set_vertex_shader(void)
6007 IDirect3DVertexShader9 *current_shader = NULL;
6008 IDirect3DVertexShader9 *shader = NULL;
6009 const IDirect3DVertexShader9Vtbl *shader_vtbl;
6010 IDirect3DDevice9 *device;
6011 ULONG refcount, i;
6012 IDirect3D9 *d3d;
6013 D3DCAPS9 caps;
6014 HWND window;
6015 HRESULT hr;
6017 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6018 0, 0, 640, 480, 0, 0, 0, 0);
6019 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6020 ok(!!d3d, "Failed to create a D3D object.\n");
6021 if (!(device = create_device(d3d, window, NULL)))
6023 skip("Failed to create a D3D device, skipping tests.\n");
6024 IDirect3D9_Release(d3d);
6025 DestroyWindow(window);
6026 return;
6029 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6030 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6031 if (!(caps.VertexShaderVersion & 0xffff))
6033 skip("No vertex shader support, skipping tests.\n");
6034 IDirect3DDevice9_Release(device);
6035 IDirect3D9_Release(d3d);
6036 DestroyWindow(window);
6037 return;
6040 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
6041 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6042 ok(!!shader, "Got unexpected shader %p.\n", shader);
6044 /* SetVertexShader() should not touch the shader's refcount. */
6045 i = get_refcount((IUnknown *)shader);
6046 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6047 refcount = get_refcount((IUnknown *)shader);
6048 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6049 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6051 /* GetVertexShader() should increase the shader's refcount by one. */
6052 i = refcount + 1;
6053 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
6054 refcount = get_refcount((IUnknown *)shader);
6055 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
6056 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6057 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6058 IDirect3DVertexShader9_Release(current_shader);
6060 /* SetVertexShader() with a bogus shader vtbl */
6061 shader_vtbl = shader->lpVtbl;
6062 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
6063 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6064 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6065 shader->lpVtbl = NULL;
6066 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6067 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6068 shader->lpVtbl = shader_vtbl;
6070 IDirect3DVertexShader9_Release(shader);
6071 refcount = IDirect3DDevice9_Release(device);
6072 ok(!refcount, "Device has %u references left.\n", refcount);
6073 IDirect3D9_Release(d3d);
6074 DestroyWindow(window);
6077 static void test_vertex_shader_constant(void)
6079 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};
6080 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6081 IDirect3DDevice9 *device;
6082 struct device_desc desc;
6083 DWORD consts_swvp;
6084 IDirect3D9 *d3d;
6085 ULONG refcount;
6086 D3DCAPS9 caps;
6087 DWORD consts;
6088 HWND window;
6089 HRESULT hr;
6091 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6092 0, 0, 640, 480, 0, 0, 0, 0);
6093 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6094 ok(!!d3d, "Failed to create a D3D object.\n");
6095 if (!(device = create_device(d3d, window, NULL)))
6097 skip("Failed to create a D3D device, skipping tests.\n");
6098 IDirect3D9_Release(d3d);
6099 DestroyWindow(window);
6100 return;
6103 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6104 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6105 if (!(caps.VertexShaderVersion & 0xffff))
6107 skip("No vertex shader support, skipping tests.\n");
6108 IDirect3DDevice9_Release(device);
6109 IDirect3D9_Release(d3d);
6110 DestroyWindow(window);
6111 return;
6113 consts = caps.MaxVertexShaderConst;
6115 /* A simple check that the stuff works at all. */
6116 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
6117 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6119 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
6120 * consts from MAX - 1. */
6121 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
6122 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6123 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6124 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6125 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6126 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6127 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6128 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6130 /* Constant -1. */
6131 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
6132 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6134 refcount = IDirect3DDevice9_Release(device);
6135 ok(!refcount, "Device has %u references left.\n", refcount);
6137 desc.device_window = window;
6138 desc.width = 640;
6139 desc.height = 480;
6140 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6142 if (!(device = create_device(d3d, window, &desc)))
6144 skip("Failed to create a D3D device, skipping tests.\n");
6145 IDirect3D9_Release(d3d);
6146 DestroyWindow(window);
6147 return;
6149 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6150 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6151 consts_swvp = caps.MaxVertexShaderConst;
6152 todo_wine
6153 ok(consts_swvp == 8192, "Unexpected consts_swvp %u.\n", consts_swvp);
6155 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6156 todo_wine
6157 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6158 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6159 todo_wine
6160 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6161 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6162 todo_wine
6163 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6164 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6165 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6166 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp, c, 1);
6167 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6169 refcount = IDirect3DDevice9_Release(device);
6170 ok(!refcount, "Device has %u references left.\n", refcount);
6172 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6173 if (!(device = create_device(d3d, window, &desc)))
6175 skip("Failed to create a D3D device, skipping tests.\n");
6176 IDirect3D9_Release(d3d);
6177 DestroyWindow(window);
6178 return;
6180 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6181 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6182 ok(consts == caps.MaxVertexShaderConst, "Unexpected caps.MaxVertexShaderConst %u, consts %u.\n",
6183 caps.MaxVertexShaderConst, consts);
6185 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6186 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6187 todo_wine
6188 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6189 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6190 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6192 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 1);
6194 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6195 todo_wine
6196 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6197 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6198 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6200 refcount = IDirect3DDevice9_Release(device);
6201 ok(!refcount, "Device has %u references left.\n", refcount);
6203 IDirect3D9_Release(d3d);
6204 DestroyWindow(window);
6207 static void test_get_set_pixel_shader(void)
6209 IDirect3DPixelShader9 *current_shader = NULL;
6210 IDirect3DPixelShader9 *shader = NULL;
6211 const IDirect3DPixelShader9Vtbl *shader_vtbl;
6212 IDirect3DDevice9 *device;
6213 ULONG refcount, i;
6214 IDirect3D9 *d3d;
6215 D3DCAPS9 caps;
6216 HWND window;
6217 HRESULT hr;
6219 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6220 0, 0, 640, 480, 0, 0, 0, 0);
6221 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6222 ok(!!d3d, "Failed to create a D3D object.\n");
6223 if (!(device = create_device(d3d, window, NULL)))
6225 skip("Failed to create a D3D device, skipping tests.\n");
6226 IDirect3D9_Release(d3d);
6227 DestroyWindow(window);
6228 return;
6231 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6232 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6233 if (!(caps.PixelShaderVersion & 0xffff))
6235 skip("No pixel shader support, skipping tests.\n");
6236 IDirect3DDevice9_Release(device);
6237 IDirect3D9_Release(d3d);
6238 DestroyWindow(window);
6239 return;
6242 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
6243 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6244 ok(!!shader, "Got unexpected shader %p.\n", shader);
6246 /* SetPixelShader() should not touch the shader's refcount. */
6247 i = get_refcount((IUnknown *)shader);
6248 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6249 refcount = get_refcount((IUnknown *)shader);
6250 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6251 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6253 /* GetPixelShader() should increase the shader's refcount by one. */
6254 i = refcount + 1;
6255 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6256 refcount = get_refcount((IUnknown *)shader);
6257 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6258 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6259 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6260 IDirect3DPixelShader9_Release(current_shader);
6262 /* SetPixelShader() with a bogus shader vtbl */
6263 shader_vtbl = shader->lpVtbl;
6264 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6265 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6266 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6267 shader->lpVtbl = NULL;
6268 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6269 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6270 shader->lpVtbl = shader_vtbl;
6272 IDirect3DPixelShader9_Release(shader);
6273 refcount = IDirect3DDevice9_Release(device);
6274 ok(!refcount, "Device has %u references left.\n", refcount);
6275 IDirect3D9_Release(d3d);
6276 DestroyWindow(window);
6279 static void test_pixel_shader_constant(void)
6281 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};
6282 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6283 IDirect3DDevice9 *device;
6284 DWORD consts = 0;
6285 IDirect3D9 *d3d;
6286 ULONG refcount;
6287 D3DCAPS9 caps;
6288 HWND window;
6289 HRESULT hr;
6291 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6292 0, 0, 640, 480, 0, 0, 0, 0);
6293 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6294 ok(!!d3d, "Failed to create a D3D object.\n");
6295 if (!(device = create_device(d3d, window, NULL)))
6297 skip("Failed to create a D3D device, skipping tests.\n");
6298 IDirect3D9_Release(d3d);
6299 DestroyWindow(window);
6300 return;
6303 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6304 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6305 if (!(caps.PixelShaderVersion & 0xffff))
6307 skip("No pixel shader support, skipping tests.\n");
6308 IDirect3DDevice9_Release(device);
6309 IDirect3D9_Release(d3d);
6310 DestroyWindow(window);
6311 return;
6314 /* A simple check that the stuff works at all. */
6315 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6316 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6318 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6319 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6320 consts = consts - 1;
6321 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6323 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6324 * pointless given the way the constant limit was determined. */
6325 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6326 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6328 /* Constant -1. */
6329 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6330 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6332 refcount = IDirect3DDevice9_Release(device);
6333 ok(!refcount, "Device has %u references left.\n", refcount);
6334 IDirect3D9_Release(d3d);
6335 DestroyWindow(window);
6338 static void test_unsupported_shaders(void)
6340 static const DWORD vs_3_0[] =
6342 0xfffe0300, /* vs_3_0 */
6343 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6344 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6345 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6346 0x0000ffff, /* end */
6349 #if 0
6350 float4 main(const float4 color : COLOR) : SV_TARGET
6352 float4 o;
6354 o = color;
6356 return o;
6358 #endif
6359 static const DWORD ps_4_0[] =
6361 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6362 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6363 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6364 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6365 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6366 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6367 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6368 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6369 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6370 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6371 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6372 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6373 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6374 0x00000000, 0x00000000, 0x00000000,
6376 #if 0
6377 vs_1_1
6378 dcl_position v0
6379 def c255, 1.0, 1.0, 1.0, 1.0
6380 add r0, v0, c255
6381 mov oPos, r0
6382 #endif
6383 static const DWORD vs_1_255[] =
6385 0xfffe0101,
6386 0x0000001f, 0x80000000, 0x900f0000,
6387 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6388 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6389 0x00000001, 0xc00f0000, 0x80e40000,
6390 0x0000ffff
6392 #if 0
6393 vs_1_1
6394 dcl_position v0
6395 def c256, 1.0, 1.0, 1.0, 1.0
6396 add r0, v0, c256
6397 mov oPos, r0
6398 #endif
6399 static const DWORD vs_1_256[] =
6401 0xfffe0101,
6402 0x0000001f, 0x80000000, 0x900f0000,
6403 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6404 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6405 0x00000001, 0xc00f0000, 0x80e40000,
6406 0x0000ffff
6408 #if 0
6409 vs_3_0
6410 dcl_position v0
6411 dcl_position o0
6412 def c256, 1.0, 1.0, 1.0, 1.0
6413 add r0, v0, c256
6414 mov o0, r0
6415 #endif
6416 static const DWORD vs_3_256[] =
6418 0xfffe0300,
6419 0x0200001f, 0x80000000, 0x900f0000,
6420 0x0200001f, 0x80000000, 0xe00f0000,
6421 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6422 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6423 0x02000001, 0xe00f0000, 0x80e40000,
6424 0x0000ffff
6426 #if 0
6427 /* This shader source generates syntax errors with the native shader assembler
6428 * due to the constant register index values.
6429 * The bytecode was modified by hand to use the intended values. */
6430 vs_3_0
6431 dcl_position v0
6432 dcl_position o0
6433 defi i16, 1, 1, 1, 1
6434 rep i16
6435 add r0, r0, v0
6436 endrep
6437 mov o0, r0
6438 #endif
6439 static const DWORD vs_3_i16[] =
6441 0xfffe0300,
6442 0x0200001f, 0x80000000, 0x900f0000,
6443 0x0200001f, 0x80000000, 0xe00f0000,
6444 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6445 0x01000026, 0xf0e40010,
6446 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6447 0x00000027,
6448 0x02000001, 0xe00f0000, 0x80e40000,
6449 0x0000ffff
6451 #if 0
6452 /* This shader source generates syntax errors with the native shader assembler
6453 * due to the constant register index values.
6454 * The bytecode was modified by hand to use the intended values. */
6455 vs_3_0
6456 dcl_position v0
6457 dcl_position o0
6458 defb b16, true
6459 mov r0, v0
6460 if b16
6461 add r0, r0, v0
6462 endif
6463 mov o0, r0
6464 #endif
6465 static const DWORD vs_3_b16[] =
6467 0xfffe0300,
6468 0x0200001f, 0x80000000, 0x900f0000,
6469 0x0200001f, 0x80000000, 0xe00f0000,
6470 0x0200002f, 0xe00f0810, 0x00000001,
6471 0x02000001, 0x800f0000, 0x90e40000,
6472 0x01000028, 0xe0e40810,
6473 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6474 0x0000002b,
6475 0x02000001, 0xe00f0000, 0x80e40000,
6476 0x0000ffff
6478 #if 0
6479 /* This shader source generates syntax errors with the native shader assembler
6480 * due to the constant register index values.
6481 * The bytecode was modified by hand to use the intended values. */
6482 ps_1_1
6483 def c8, 1.0, 1.0, 1.0, 1.0
6484 add r0, v0, c8
6485 #endif
6486 static const DWORD ps_1_8[] =
6488 0xffff0101,
6489 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6490 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6491 0x0000ffff
6493 #if 0
6494 /* This shader source generates syntax errors with the native shader assembler
6495 * due to the constant register index values.
6496 * The bytecode was modified by hand to use the intended values. */
6497 ps_2_0
6498 def c32, 1.0, 1.0, 1.0, 1.0
6499 add oC0, v0, c32
6500 #endif
6501 static const DWORD ps_2_32[] =
6503 0xffff0200,
6504 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6505 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6506 0x0000ffff
6508 #if 0
6509 /* This shader source generates syntax errors with the native shader assembler
6510 * due to the constant register index values.
6511 * The bytecode was modified by hand to use the intended values. */
6512 ps_3_0
6513 dcl_color0 v0
6514 def c224, 1.0, 1.0, 1.0, 1.0
6515 add oC0, v0, c224
6516 #endif
6517 static const DWORD ps_3_224[] =
6519 0xffff0300,
6520 0x0200001f, 0x8000000a, 0x900f0000,
6521 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6522 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6523 0x0000ffff
6525 #if 0
6526 /* This shader source generates syntax errors with the native shader assembler
6527 * due to the constant register index values.
6528 * The bytecode was modified by hand to use the intended values. */
6529 ps_2_0
6530 defb b0, true
6531 defi i0, 1, 1, 1, 1
6532 rep i0
6533 if b0
6534 add r0, r0, v0
6535 endif
6536 endrep
6537 mov oC0, r0
6538 #endif
6539 static const DWORD ps_2_0_boolint[] =
6541 0xffff0200,
6542 0x0200002f, 0xe00f0800, 0x00000001,
6543 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6544 0x01000026, 0xf0e40000,
6545 0x01000028, 0xe0e40800,
6546 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6547 0x0000002b,
6548 0x00000027,
6549 0x02000001, 0x800f0800, 0x80e40000,
6550 0x0000ffff
6553 IDirect3DVertexShader9 *vs = NULL;
6554 IDirect3DPixelShader9 *ps = NULL;
6555 IDirect3DDevice9 *device;
6556 struct device_desc desc;
6557 IDirect3D9 * d3d;
6558 ULONG refcount;
6559 D3DCAPS9 caps;
6560 HWND window;
6561 HRESULT hr;
6563 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6564 0, 0, 640, 480, 0, 0, 0, 0);
6565 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6566 ok(!!d3d, "Failed to create a D3D object.\n");
6567 if (!(device = create_device(d3d, window, NULL)))
6569 skip("Failed to create a D3D device, skipping tests.\n");
6570 IDirect3D9_Release(d3d);
6571 DestroyWindow(window);
6572 return;
6575 /* These should always fail, regardless of supported shader version. */
6576 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6577 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6578 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6579 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6580 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6581 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6583 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6584 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6585 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6587 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6588 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6589 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6591 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6592 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6594 else
6596 skip("GPU supports SM2+, skipping SM1 test.\n");
6599 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6601 else
6603 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6605 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6606 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6607 IDirect3DVertexShader9_Release(vs);
6608 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6609 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6610 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6611 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6612 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6613 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6614 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6615 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6618 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6620 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6621 goto cleanup;
6623 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6624 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6625 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6626 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6627 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6628 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6629 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6630 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6631 if (ps)
6632 IDirect3DPixelShader9_Release(ps);
6634 refcount = IDirect3DDevice9_Release(device);
6635 ok(!refcount, "Device has %u references left.\n", refcount);
6637 desc.device_window = window;
6638 desc.width = 640;
6639 desc.height = 480;
6640 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6642 if (!(device = create_device(d3d, window, &desc)))
6644 skip("Failed to create a D3D device, skipping tests.\n");
6645 IDirect3D9_Release(d3d);
6646 DestroyWindow(window);
6647 return;
6650 vs = NULL;
6651 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6652 todo_wine
6653 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6654 if (vs)
6655 IDirect3DVertexShader9_Release(vs);
6656 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6657 todo_wine
6658 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6659 if (vs)
6660 IDirect3DVertexShader9_Release(vs);
6662 refcount = IDirect3DDevice9_Release(device);
6663 ok(!refcount, "Device has %u references left.\n", refcount);
6665 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6666 if (!(device = create_device(d3d, window, &desc)))
6668 skip("Failed to create a D3D device, skipping tests.\n");
6669 IDirect3D9_Release(d3d);
6670 DestroyWindow(window);
6671 return;
6673 hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6674 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6676 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6677 todo_wine
6678 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6679 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6680 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6681 if (vs)
6682 IDirect3DVertexShader9_Release(vs);
6684 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6685 todo_wine
6686 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6687 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6688 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6689 if (vs)
6690 IDirect3DVertexShader9_Release(vs);
6692 cleanup:
6693 refcount = IDirect3DDevice9_Release(device);
6694 ok(!refcount, "Device has %u references left.\n", refcount);
6695 IDirect3D9_Release(d3d);
6696 DestroyWindow(window);
6699 /* Test the default texture stage state values */
6700 static void test_texture_stage_states(void)
6702 IDirect3DDevice9 *device;
6703 IDirect3D9 *d3d;
6704 unsigned int i;
6705 ULONG refcount;
6706 D3DCAPS9 caps;
6707 DWORD value;
6708 HWND window;
6709 HRESULT hr;
6711 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6712 0, 0, 640, 480, 0, 0, 0, 0);
6713 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6714 ok(!!d3d, "Failed to create a D3D object.\n");
6715 if (!(device = create_device(d3d, window, NULL)))
6717 skip("Failed to create a D3D device, skipping tests.\n");
6718 IDirect3D9_Release(d3d);
6719 DestroyWindow(window);
6720 return;
6723 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6724 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6726 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6728 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6729 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6730 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6731 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6732 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6733 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6734 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6735 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6736 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6737 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6738 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6739 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6740 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6741 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6742 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6743 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6744 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6745 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6746 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6747 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6748 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6749 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6750 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6751 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6752 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6753 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6754 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6755 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6756 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6757 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6758 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6759 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6760 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6761 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6762 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6763 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6764 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6765 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6766 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6767 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6768 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6769 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6770 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6771 ok(value == D3DTTFF_DISABLE,
6772 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6773 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6774 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6775 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6776 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6777 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6778 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6779 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6780 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6781 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6782 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6783 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6784 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6787 refcount = IDirect3DDevice9_Release(device);
6788 ok(!refcount, "Device has %u references left.\n", refcount);
6789 IDirect3D9_Release(d3d);
6790 DestroyWindow(window);
6793 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6795 IDirect3DCubeTexture9 *texture;
6796 IDirect3D9 *d3d;
6797 HRESULT hr;
6799 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6800 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6801 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6802 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6803 IDirect3D9_Release(d3d);
6804 if (hr != D3D_OK)
6806 skip("No cube mipmap generation support, skipping tests.\n");
6807 return;
6810 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6811 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6812 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6813 IDirect3DCubeTexture9_Release(texture);
6815 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6816 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6817 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6818 IDirect3DCubeTexture9_Release(texture);
6821 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6823 IDirect3DCubeTexture9 *texture;
6824 IDirect3DSurface9 *surface;
6825 D3DSURFACE_DESC desc;
6826 DWORD levels;
6827 HRESULT hr;
6828 D3DCAPS9 caps;
6830 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6831 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6832 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6833 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6835 skip("Failed to create cube texture, skipping tests.\n");
6836 return;
6839 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6840 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6841 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6842 else
6843 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6845 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6846 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6847 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6848 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6849 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6850 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6852 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6853 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6854 IDirect3DSurface9_Release(surface);
6855 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6856 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6857 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6858 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6860 IDirect3DCubeTexture9_Release(texture);
6863 static void test_cube_textures(void)
6865 IDirect3DCubeTexture9 *texture;
6866 IDirect3DDevice9 *device;
6867 IDirect3D9 *d3d;
6868 ULONG refcount;
6869 D3DCAPS9 caps;
6870 HWND window;
6871 HRESULT hr;
6873 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6874 0, 0, 640, 480, 0, 0, 0, 0);
6875 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6876 ok(!!d3d, "Failed to create a D3D object.\n");
6877 if (!(device = create_device(d3d, window, NULL)))
6879 skip("Failed to create a D3D device, skipping tests.\n");
6880 IDirect3D9_Release(d3d);
6881 DestroyWindow(window);
6882 return;
6885 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6886 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6888 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
6890 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6891 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
6892 IDirect3DCubeTexture9_Release(texture);
6893 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6894 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
6895 IDirect3DCubeTexture9_Release(texture);
6896 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6897 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
6898 IDirect3DCubeTexture9_Release(texture);
6900 else
6902 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6903 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
6904 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6905 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
6906 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6907 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
6909 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
6910 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
6911 IDirect3DCubeTexture9_Release(texture);
6913 test_cube_texture_mipmap_gen(device);
6914 test_cube_texture_levels(device);
6916 refcount = IDirect3DDevice9_Release(device);
6917 ok(!refcount, "Device has %u references left.\n", refcount);
6918 IDirect3D9_Release(d3d);
6919 DestroyWindow(window);
6922 static void test_mipmap_gen(void)
6924 D3DTEXTUREFILTERTYPE filter_type;
6925 IDirect3DTexture9 *texture;
6926 IDirect3DSurface9 *surface;
6927 IDirect3DDevice9 *device;
6928 D3DSURFACE_DESC desc;
6929 D3DLOCKED_RECT lr;
6930 IDirect3D9 *d3d;
6931 ULONG refcount;
6932 unsigned int i;
6933 DWORD levels;
6934 HWND window;
6935 HRESULT hr;
6937 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6938 ok(!!d3d, "Failed to create a D3D object.\n");
6940 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6941 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK)
6943 skip("No mipmap generation support, skipping tests.\n");
6944 IDirect3D9_Release(d3d);
6945 return;
6948 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6949 0, 0, 640, 480, 0, 0, 0, 0);
6950 if (!(device = create_device(d3d, window, NULL)))
6952 skip("Failed to create a D3D device, skipping tests.\n");
6953 IDirect3D9_Release(d3d);
6954 DestroyWindow(window);
6955 return;
6958 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6959 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6960 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6961 IDirect3DTexture9_Release(texture);
6963 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6964 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6965 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6967 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6968 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
6969 "Got unexpected filter_type %#x.\n", filter_type);
6970 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
6971 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6972 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
6973 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6974 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6975 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
6976 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
6977 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6979 levels = IDirect3DTexture9_GetLevelCount(texture);
6980 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6982 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
6984 surface = NULL;
6985 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
6986 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6987 if (surface)
6988 IDirect3DSurface9_Release(surface);
6990 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
6991 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6993 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
6994 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6995 if (SUCCEEDED(hr))
6997 hr = IDirect3DTexture9_UnlockRect(texture, i);
6998 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7001 IDirect3DTexture9_Release(texture);
7003 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
7004 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7005 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7006 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
7007 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7008 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7010 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
7011 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7012 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7013 levels = IDirect3DTexture9_GetLevelCount(texture);
7014 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7015 IDirect3DTexture9_Release(texture);
7017 refcount = IDirect3DDevice9_Release(device);
7018 ok(!refcount, "Device has %u references left.\n", refcount);
7019 IDirect3D9_Release(d3d);
7020 DestroyWindow(window);
7023 static void test_filter(void)
7025 static const struct
7027 DWORD magfilter, minfilter, mipfilter;
7028 BOOL has_texture;
7029 HRESULT result;
7031 tests[] =
7033 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7034 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7035 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7036 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
7037 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
7039 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7040 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7041 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
7042 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
7044 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7045 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7046 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
7047 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
7048 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
7050 IDirect3DTexture9 *texture;
7051 IDirect3DDevice9 *device;
7052 IDirect3D9 *d3d;
7053 unsigned int i;
7054 ULONG refcount;
7055 DWORD passes;
7056 HWND window;
7057 HRESULT hr;
7059 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7060 ok(!!d3d, "Failed to create a D3D object.\n");
7062 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7063 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7065 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
7066 IDirect3D9_Release(d3d);
7067 return;
7070 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7071 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7073 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
7074 IDirect3D9_Release(d3d);
7075 return;
7078 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7079 0, 0, 640, 480, 0, 0, 0, 0);
7080 if (!(device = create_device(d3d, window, NULL)))
7082 skip("Failed to create a D3D device, skipping tests.\n");
7083 IDirect3D9_Release(d3d);
7084 DestroyWindow(window);
7085 return;
7088 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
7089 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
7090 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7092 /* Needed for ValidateDevice(). */
7093 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7094 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
7096 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7098 if (tests[i].has_texture)
7100 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
7101 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7103 else
7105 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7106 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7109 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
7110 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7111 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
7112 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7113 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
7114 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7116 passes = 0xdeadbeef;
7117 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
7118 ok(hr == tests[i].result,
7119 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
7120 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
7121 tests[i].mipfilter, tests[i].has_texture);
7122 if (SUCCEEDED(hr))
7123 ok(!!passes, "Got unexpected passes %#x.\n", passes);
7124 else
7125 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
7128 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7129 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7130 IDirect3DTexture9_Release(texture);
7132 refcount = IDirect3DDevice9_Release(device);
7133 ok(!refcount, "Device has %u references left.\n", refcount);
7134 IDirect3D9_Release(d3d);
7135 DestroyWindow(window);
7138 static void test_get_set_texture(void)
7140 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
7141 IDirect3DBaseTexture9 *texture;
7142 IDirect3DDevice9 *device;
7143 IDirect3D9 *d3d;
7144 ULONG refcount;
7145 HWND window;
7146 HRESULT hr;
7148 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7149 0, 0, 640, 480, 0, 0, 0, 0);
7150 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7151 ok(!!d3d, "Failed to create a D3D object.\n");
7152 if (!(device = create_device(d3d, window, NULL)))
7154 skip("Failed to create a D3D device, skipping tests.\n");
7155 IDirect3D9_Release(d3d);
7156 DestroyWindow(window);
7157 return;
7160 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
7161 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7162 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7163 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
7164 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7165 ok(!texture, "Got unexpected texture %p.\n", texture);
7167 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
7168 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
7169 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7170 texture_vtbl = texture->lpVtbl;
7171 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
7172 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7173 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7174 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7175 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7176 texture->lpVtbl = NULL;
7177 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7178 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7179 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7180 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7181 texture->lpVtbl = texture_vtbl;
7182 IDirect3DBaseTexture9_Release(texture);
7184 refcount = IDirect3DDevice9_Release(device);
7185 ok(!refcount, "Device has %u references left.\n", refcount);
7186 IDirect3D9_Release(d3d);
7187 DestroyWindow(window);
7190 static void test_lod(void)
7192 IDirect3DTexture9 *texture;
7193 IDirect3DDevice9 *device;
7194 IDirect3D9 *d3d;
7195 ULONG refcount;
7196 HWND window;
7197 HRESULT hr;
7198 DWORD ret;
7200 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7201 0, 0, 640, 480, 0, 0, 0, 0);
7202 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7203 ok(!!d3d, "Failed to create a D3D object.\n");
7204 if (!(device = create_device(d3d, window, NULL)))
7206 skip("Failed to create a D3D device, skipping tests.\n");
7207 IDirect3D9_Release(d3d);
7208 DestroyWindow(window);
7209 return;
7212 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
7213 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7214 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7216 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
7217 * return a HRESULT, so it can't return a normal error. Instead, the call
7218 * is simply ignored. */
7219 ret = IDirect3DTexture9_SetLOD(texture, 0);
7220 ok(!ret, "Got unexpected ret %u.\n", ret);
7221 ret = IDirect3DTexture9_SetLOD(texture, 1);
7222 ok(!ret, "Got unexpected ret %u.\n", ret);
7223 ret = IDirect3DTexture9_SetLOD(texture, 2);
7224 ok(!ret, "Got unexpected ret %u.\n", ret);
7225 ret = IDirect3DTexture9_GetLOD(texture);
7226 ok(!ret, "Got unexpected ret %u.\n", ret);
7228 IDirect3DTexture9_Release(texture);
7229 refcount = IDirect3DDevice9_Release(device);
7230 ok(!refcount, "Device has %u references left.\n", refcount);
7231 IDirect3D9_Release(d3d);
7232 DestroyWindow(window);
7235 static void test_surface_get_container(void)
7237 IDirect3DTexture9 *texture = NULL;
7238 IDirect3DSurface9 *surface = NULL;
7239 IDirect3DDevice9 *device;
7240 IUnknown *container;
7241 IDirect3D9 *d3d;
7242 ULONG refcount;
7243 HWND window;
7244 HRESULT hr;
7246 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7247 0, 0, 640, 480, 0, 0, 0, 0);
7248 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7249 ok(!!d3d, "Failed to create a D3D object.\n");
7250 if (!(device = create_device(d3d, window, NULL)))
7252 skip("Failed to create a D3D device, skipping tests.\n");
7253 IDirect3D9_Release(d3d);
7254 DestroyWindow(window);
7255 return;
7258 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
7259 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7260 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7261 ok(!!texture, "Got unexpected texture %p.\n", texture);
7263 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7264 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7265 ok(!!surface, "Got unexpected surface %p.\n", surface);
7267 /* These should work... */
7268 container = NULL;
7269 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
7270 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7271 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7272 IUnknown_Release(container);
7274 container = NULL;
7275 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
7276 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7277 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7278 IUnknown_Release(container);
7280 container = NULL;
7281 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
7282 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7283 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7284 IUnknown_Release(container);
7286 container = NULL;
7287 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
7288 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7289 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7290 IUnknown_Release(container);
7292 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
7293 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
7294 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7295 ok(!container, "Got unexpected container %p.\n", container);
7297 IDirect3DSurface9_Release(surface);
7298 IDirect3DTexture9_Release(texture);
7299 refcount = IDirect3DDevice9_Release(device);
7300 ok(!refcount, "Device has %u references left.\n", refcount);
7301 IDirect3D9_Release(d3d);
7302 DestroyWindow(window);
7305 static void test_surface_alignment(void)
7307 IDirect3DSurface9 *surface;
7308 IDirect3DDevice9 *device;
7309 D3DLOCKED_RECT lr;
7310 unsigned int i, j;
7311 IDirect3D9 *d3d;
7312 ULONG refcount;
7313 HWND window;
7314 HRESULT hr;
7316 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7317 0, 0, 640, 480, 0, 0, 0, 0);
7318 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7319 ok(!!d3d, "Failed to create a D3D object.\n");
7320 if (!(device = create_device(d3d, window, NULL)))
7322 skip("Failed to create a D3D device, skipping tests.\n");
7323 IDirect3D9_Release(d3d);
7324 DestroyWindow(window);
7325 return;
7328 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7329 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7330 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7331 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7333 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7334 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7335 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7336 /* Some applications also depend on the exact pitch, rather than just the
7337 * alignment. */
7338 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7339 hr = IDirect3DSurface9_UnlockRect(surface);
7340 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7341 IDirect3DSurface9_Release(surface);
7343 for (i = 0; i < 5; ++i)
7345 IDirect3DTexture9 *texture;
7346 unsigned int level_count;
7347 D3DSURFACE_DESC desc;
7348 int expected_pitch;
7350 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7351 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7352 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7353 if (FAILED(hr))
7355 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7356 continue;
7359 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7360 for (j = 0; j < level_count; ++j)
7362 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7363 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7364 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7365 hr = IDirect3DTexture9_UnlockRect(texture, j);
7366 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7368 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7369 if (i > 0)
7370 expected_pitch <<= 1;
7371 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7372 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7374 IDirect3DTexture9_Release(texture);
7377 refcount = IDirect3DDevice9_Release(device);
7378 ok(!refcount, "Device has %u references left.\n", refcount);
7379 IDirect3D9_Release(d3d);
7380 DestroyWindow(window);
7383 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7384 * different from regular formats. This test verifies we return the correct
7385 * memory offsets. */
7386 static void test_lockrect_offset(void)
7388 static const struct
7390 D3DFORMAT format;
7391 const char *name;
7392 unsigned int block_width;
7393 unsigned int block_height;
7394 unsigned int block_size;
7396 dxt_formats[] =
7398 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7399 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7400 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7401 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7402 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7403 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7404 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7406 unsigned int expected_offset, offset, i;
7407 const RECT rect = {60, 60, 68, 68};
7408 IDirect3DSurface9 *surface;
7409 D3DLOCKED_RECT locked_rect;
7410 IDirect3DDevice9 *device;
7411 int expected_pitch;
7412 IDirect3D9 *d3d;
7413 ULONG refcount;
7414 HWND window;
7415 BYTE *base;
7416 HRESULT hr;
7418 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7419 0, 0, 640, 480, 0, 0, 0, 0);
7420 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7421 ok(!!d3d, "Failed to create a D3D object.\n");
7422 if (!(device = create_device(d3d, window, NULL)))
7424 skip("Failed to create a D3D device, skipping tests.\n");
7425 IDirect3D9_Release(d3d);
7426 DestroyWindow(window);
7427 return;
7430 for (i = 0; i < ARRAY_SIZE(dxt_formats); ++i)
7432 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7433 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7435 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7436 continue;
7439 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7440 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7441 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7443 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7444 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7446 base = locked_rect.pBits;
7447 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7448 * dxt_formats[i].block_size;
7449 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7450 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7452 hr = IDirect3DSurface9_UnlockRect(surface);
7453 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7455 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7456 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7458 offset = (BYTE *)locked_rect.pBits - base;
7459 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7460 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7461 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7462 offset, dxt_formats[i].name, expected_offset);
7464 hr = IDirect3DSurface9_UnlockRect(surface);
7465 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7467 IDirect3DSurface9_Release(surface);
7470 refcount = IDirect3DDevice9_Release(device);
7471 ok(!refcount, "Device has %u references left.\n", refcount);
7472 IDirect3D9_Release(d3d);
7473 DestroyWindow(window);
7476 static void test_lockrect_invalid(void)
7478 static const struct
7480 RECT rect;
7481 HRESULT win7_result;
7483 test_data[] =
7485 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7486 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7487 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7488 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7489 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7490 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7491 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7492 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7493 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7494 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7495 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7496 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7497 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7499 static const RECT test_rect_2 = {0, 0, 8, 8};
7500 IDirect3DSurface9 *surface = NULL;
7501 D3DLOCKED_RECT locked_rect;
7502 IDirect3DDevice9 *device;
7503 IDirect3DTexture9 *texture;
7504 IDirect3DCubeTexture9 *cube_texture;
7505 HRESULT hr, expected_hr;
7506 unsigned int i, r;
7507 IDirect3D9 *d3d;
7508 ULONG refcount;
7509 HWND window;
7510 BYTE *base;
7511 static const struct
7513 D3DRESOURCETYPE type;
7514 D3DPOOL pool;
7515 const char *name;
7517 resources[] =
7519 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7520 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7521 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7522 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7523 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7524 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7525 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7528 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7529 0, 0, 640, 480, 0, 0, 0, 0);
7530 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7531 ok(!!d3d, "Failed to create a D3D object.\n");
7532 if (!(device = create_device(d3d, window, NULL)))
7534 skip("Failed to create a D3D device, skipping tests.\n");
7535 IDirect3D9_Release(d3d);
7536 DestroyWindow(window);
7537 return;
7540 for (r = 0; r < ARRAY_SIZE(resources); ++r)
7542 texture = NULL;
7543 cube_texture = NULL;
7544 switch (resources[r].type)
7546 case D3DRTYPE_SURFACE:
7547 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7548 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7549 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7550 hr, resources[r].name);
7551 break;
7553 case D3DRTYPE_TEXTURE:
7554 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7555 resources[r].pool, &texture, NULL);
7556 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7557 hr, resources[r].name);
7558 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7559 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7560 hr, resources[r].name);
7561 break;
7563 case D3DRTYPE_CUBETEXTURE:
7564 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7565 resources[r].pool, &cube_texture, NULL);
7566 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7567 hr, resources[r].name);
7568 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7569 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7570 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7571 hr, resources[r].name);
7572 break;
7574 default:
7575 break;
7578 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7579 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7580 base = locked_rect.pBits;
7581 hr = IDirect3DSurface9_UnlockRect(surface);
7582 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7583 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
7584 hr = IDirect3DSurface9_UnlockRect(surface);
7585 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
7587 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7589 unsigned int offset, expected_offset;
7590 const RECT *rect = &test_data[i].rect;
7592 locked_rect.pBits = (BYTE *)0xdeadbeef;
7593 locked_rect.Pitch = 0xdeadbeef;
7595 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7596 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7597 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7598 * one broken. */
7599 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7600 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7601 wine_dbgstr_rect(rect), hr, resources[r].name);
7602 if (FAILED(hr))
7603 continue;
7605 offset = (BYTE *)locked_rect.pBits - base;
7606 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7607 ok(offset == expected_offset,
7608 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7609 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7611 hr = IDirect3DSurface9_UnlockRect(surface);
7612 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7614 if (texture)
7616 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7617 ok(SUCCEEDED(hr),
7618 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7619 wine_dbgstr_rect(rect), hr, resources[r].name);
7620 if (FAILED(hr))
7621 continue;
7623 offset = (BYTE *)locked_rect.pBits - base;
7624 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7625 ok(offset == expected_offset,
7626 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7627 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7629 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7630 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7632 if (cube_texture)
7634 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7635 &locked_rect, rect, 0);
7636 ok(SUCCEEDED(hr),
7637 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7638 wine_dbgstr_rect(rect), hr, resources[r].name);
7639 if (FAILED(hr))
7640 continue;
7642 offset = (BYTE *)locked_rect.pBits - base;
7643 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7644 ok(offset == expected_offset,
7645 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7646 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7648 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7649 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7653 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7654 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7655 locked_rect.pBits = (BYTE *)0xdeadbeef;
7656 locked_rect.Pitch = 1;
7657 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7658 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7659 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7660 locked_rect.pBits, resources[r].name);
7661 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7662 locked_rect.Pitch, resources[r].name);
7663 hr = IDirect3DSurface9_UnlockRect(surface);
7664 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7666 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7667 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7668 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7669 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7670 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7671 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7672 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7673 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7674 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7675 hr = IDirect3DSurface9_UnlockRect(surface);
7676 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7678 IDirect3DSurface9_Release(surface);
7680 if (texture)
7682 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7683 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7684 hr, resources[r].name);
7685 locked_rect.pBits = (BYTE *)0xdeadbeef;
7686 locked_rect.Pitch = 1;
7687 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7688 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7689 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7690 locked_rect.pBits, resources[r].name);
7691 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7692 locked_rect.Pitch, resources[r].name);
7693 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7694 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7695 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7696 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7697 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7698 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7700 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7701 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7702 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7703 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7704 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7705 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7706 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7707 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7708 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7709 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7710 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7712 IDirect3DTexture9_Release(texture);
7714 if (cube_texture)
7716 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7717 &locked_rect, NULL, 0);
7718 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7719 hr, resources[r].name);
7720 locked_rect.pBits = (BYTE *)0xdeadbeef;
7721 locked_rect.Pitch = 1;
7722 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7723 &locked_rect, NULL, 0);
7724 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7725 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7726 locked_rect.pBits, resources[r].name);
7727 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7728 locked_rect.Pitch, resources[r].name);
7729 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7730 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7731 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7732 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7733 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7734 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7736 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7737 &locked_rect, &test_data[0].rect, 0);
7738 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7739 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7740 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7741 &locked_rect, &test_data[0].rect, 0);
7742 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7743 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7744 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7745 &locked_rect, &test_rect_2, 0);
7746 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7747 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7748 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7749 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7751 IDirect3DCubeTexture9_Release(cube_texture);
7755 refcount = IDirect3DDevice9_Release(device);
7756 ok(!refcount, "Device has %u references left.\n", refcount);
7757 IDirect3D9_Release(d3d);
7758 DestroyWindow(window);
7761 static void test_private_data(void)
7763 ULONG refcount, expected_refcount;
7764 IDirect3DTexture9 *texture;
7765 IDirect3DSurface9 *surface, *surface2;
7766 IDirect3DDevice9 *device;
7767 IDirect3D9 *d3d;
7768 IUnknown *ptr;
7769 HWND window;
7770 HRESULT hr;
7771 DWORD size;
7772 DWORD data[4] = {1, 2, 3, 4};
7773 static const GUID d3d9_private_data_test_guid2 =
7775 0x2e5afac2,
7776 0x87b5,
7777 0x4c10,
7778 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7781 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7782 0, 0, 640, 480, 0, 0, 0, 0);
7783 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7784 ok(!!d3d, "Failed to create a D3D object.\n");
7785 if (!(device = create_device(d3d, window, NULL)))
7787 skip("Failed to create a D3D device, skipping tests.\n");
7788 IDirect3D9_Release(d3d);
7789 DestroyWindow(window);
7790 return;
7793 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7794 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7795 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7797 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7798 device, 0, D3DSPD_IUNKNOWN);
7799 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7800 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7801 device, 5, D3DSPD_IUNKNOWN);
7802 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7803 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7804 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7805 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7807 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7808 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7809 sizeof(device), D3DSPD_IUNKNOWN);
7810 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7811 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7812 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7813 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7814 size = sizeof(ptr);
7815 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7816 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7817 IUnknown_Release(ptr);
7818 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7819 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7821 refcount = get_refcount((IUnknown *)device);
7822 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7823 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7824 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7825 expected_refcount = refcount + 1;
7826 refcount = get_refcount((IUnknown *)device);
7827 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7828 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7829 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7830 expected_refcount = refcount - 1;
7831 refcount = get_refcount((IUnknown *)device);
7832 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7834 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7835 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7836 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7837 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7838 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7839 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7840 refcount = get_refcount((IUnknown *)device);
7841 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7843 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7844 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7845 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7846 size = 2 * sizeof(ptr);
7847 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7848 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7849 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7850 expected_refcount = refcount + 2;
7851 refcount = get_refcount((IUnknown *)device);
7852 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7853 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
7854 IUnknown_Release(ptr);
7855 expected_refcount--;
7857 ptr = (IUnknown *)0xdeadbeef;
7858 size = 1;
7859 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7860 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7861 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7862 size = 2 * sizeof(ptr);
7863 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7864 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7865 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7866 refcount = get_refcount((IUnknown *)device);
7867 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7868 size = 1;
7869 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7870 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7871 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7872 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7873 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
7874 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7875 size = 0xdeadbabe;
7876 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
7877 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7878 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7879 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7880 /* GetPrivateData with size = NULL causes an access violation on Windows if the
7881 * requested data exists. */
7883 /* Destroying the surface frees the held reference. */
7884 IDirect3DSurface9_Release(surface);
7885 expected_refcount = refcount - 2;
7886 refcount = get_refcount((IUnknown *)device);
7887 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7889 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
7890 &texture, NULL);
7891 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7892 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7893 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
7894 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
7895 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
7897 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7898 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7900 memset(data, 0, sizeof(data));
7901 size = sizeof(data);
7902 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
7903 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7904 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
7905 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7906 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
7907 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
7909 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
7910 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7912 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7913 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7914 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
7915 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7917 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7918 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7920 IDirect3DSurface9_Release(surface2);
7921 IDirect3DSurface9_Release(surface);
7922 IDirect3DTexture9_Release(texture);
7924 refcount = IDirect3DDevice9_Release(device);
7925 ok(!refcount, "Device has %u references left.\n", refcount);
7926 IDirect3D9_Release(d3d);
7927 DestroyWindow(window);
7930 static void test_getdc(void)
7932 static const struct
7934 const char *name;
7935 D3DFORMAT format;
7936 unsigned int bit_count;
7937 DWORD mask_r, mask_g, mask_b;
7938 BOOL getdc_supported;
7940 testdata[] =
7942 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7943 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
7944 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
7945 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7946 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
7947 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
7948 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7949 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7950 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7951 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7952 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
7953 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7954 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7955 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7956 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
7957 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
7958 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7959 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7960 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7961 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
7963 IDirect3DSurface9 *surface, *surface2;
7964 IDirect3DCubeTexture9 *cube_texture;
7965 struct device_desc device_desc;
7966 IDirect3DTexture9 *texture;
7967 IDirect3DDevice9 *device;
7968 D3DLOCKED_RECT map_desc;
7969 IDirect3D9 *d3d;
7970 unsigned int i;
7971 ULONG refcount;
7972 HWND window;
7973 HDC dc, dc2;
7974 HRESULT hr;
7976 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7977 0, 0, 640, 480, 0, 0, 0, 0);
7978 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7979 ok(!!d3d, "Failed to create a D3D object.\n");
7980 if (!(device = create_device(d3d, window, NULL)))
7982 skip("Failed to create a D3D device, skipping tests.\n");
7983 IDirect3D9_Release(d3d);
7984 DestroyWindow(window);
7985 return;
7988 for (i = 0; i < ARRAY_SIZE(testdata); ++i)
7990 texture = NULL;
7991 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7992 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
7993 if (FAILED(hr))
7995 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
7996 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
7997 if (FAILED(hr))
7999 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8000 continue;
8002 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8003 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8006 dc = (void *)0x1234;
8007 hr = IDirect3DSurface9_GetDC(surface, &dc);
8008 if (testdata[i].getdc_supported)
8009 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8010 else
8011 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8013 if (SUCCEEDED(hr))
8015 unsigned int width_bytes;
8016 DIBSECTION dib;
8017 HBITMAP bitmap;
8018 DWORD type;
8019 int size;
8021 type = GetObjectType(dc);
8022 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8023 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8024 type = GetObjectType(bitmap);
8025 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8027 size = GetObjectA(bitmap, sizeof(dib), &dib);
8028 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
8029 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
8030 dib.dsBm.bmType, testdata[i].name);
8031 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
8032 dib.dsBm.bmWidth, testdata[i].name);
8033 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
8034 dib.dsBm.bmHeight, testdata[i].name);
8035 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
8036 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
8037 dib.dsBm.bmWidthBytes, testdata[i].name);
8038 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
8039 dib.dsBm.bmPlanes, testdata[i].name);
8040 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
8041 "Got unexpected bit count %d for format %s.\n",
8042 dib.dsBm.bmBitsPixel, testdata[i].name);
8043 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
8044 dib.dsBm.bmBits, testdata[i].name);
8046 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
8047 dib.dsBmih.biSize, testdata[i].name);
8048 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
8049 dib.dsBmih.biHeight, testdata[i].name);
8050 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
8051 dib.dsBmih.biHeight, testdata[i].name);
8052 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
8053 dib.dsBmih.biPlanes, testdata[i].name);
8054 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
8055 dib.dsBmih.biBitCount, testdata[i].name);
8056 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
8057 "Got unexpected compression %#x for format %s.\n",
8058 dib.dsBmih.biCompression, testdata[i].name);
8059 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
8060 dib.dsBmih.biSizeImage, testdata[i].name);
8061 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
8062 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
8063 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
8064 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
8065 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
8066 dib.dsBmih.biClrUsed, testdata[i].name);
8067 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
8068 dib.dsBmih.biClrImportant, testdata[i].name);
8070 if (dib.dsBmih.biCompression == BI_BITFIELDS)
8072 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
8073 && dib.dsBitfields[2] == testdata[i].mask_b,
8074 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8075 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8077 else
8079 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
8080 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8081 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8083 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
8084 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
8086 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8087 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
8089 else
8091 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
8094 IDirect3DSurface9_Release(surface);
8095 if (texture)
8096 IDirect3DTexture9_Release(texture);
8098 if (!testdata[i].getdc_supported)
8099 continue;
8101 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
8102 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
8104 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8105 continue;
8108 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
8109 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8110 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
8111 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8113 hr = IDirect3DSurface9_GetDC(surface, &dc);
8114 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8115 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8116 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8117 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8118 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8119 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8120 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8122 hr = IDirect3DSurface9_GetDC(surface, &dc);
8123 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8124 dc2 = (void *)0x1234;
8125 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8126 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8127 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
8128 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8129 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8130 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8131 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8133 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8134 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8135 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8136 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8137 hr = IDirect3DSurface9_UnlockRect(surface);
8138 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8139 hr = IDirect3DSurface9_UnlockRect(surface);
8140 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8142 hr = IDirect3DSurface9_GetDC(surface, &dc);
8143 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8144 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8145 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8146 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8147 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8149 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8150 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8151 hr = IDirect3DSurface9_GetDC(surface, &dc);
8152 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8153 hr = IDirect3DSurface9_UnlockRect(surface);
8154 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8156 hr = IDirect3DSurface9_GetDC(surface, &dc);
8157 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8158 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
8159 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8160 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
8161 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8162 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8163 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8165 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8166 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8167 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8168 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8169 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
8170 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8171 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8172 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8174 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8175 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8176 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8177 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8178 hr = IDirect3DSurface9_UnlockRect(surface2);
8179 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8180 hr = IDirect3DSurface9_UnlockRect(surface);
8181 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8183 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8184 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8185 hr = IDirect3DSurface9_GetDC(surface, &dc);
8186 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8187 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8188 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8189 hr = IDirect3DSurface9_UnlockRect(surface);
8190 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8192 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8193 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8194 hr = IDirect3DSurface9_GetDC(surface, &dc);
8195 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8196 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8197 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8198 hr = IDirect3DSurface9_UnlockRect(surface2);
8199 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8201 hr = IDirect3DSurface9_GetDC(surface, &dc);
8202 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8203 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8204 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8205 hr = IDirect3DSurface9_UnlockRect(surface2);
8206 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8207 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8208 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8210 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8211 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8212 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8213 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8214 hr = IDirect3DSurface9_UnlockRect(surface);
8215 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8216 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8217 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8219 hr = IDirect3DSurface9_UnlockRect(surface);
8220 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8221 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8222 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8223 hr = IDirect3DSurface9_UnlockRect(surface);
8224 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8225 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8226 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8227 hr = IDirect3DSurface9_UnlockRect(surface);
8228 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8230 hr = IDirect3DSurface9_UnlockRect(surface2);
8231 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8232 hr = IDirect3DSurface9_GetDC(surface, &dc);
8233 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8234 hr = IDirect3DSurface9_UnlockRect(surface2);
8235 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8236 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8237 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8238 hr = IDirect3DSurface9_UnlockRect(surface2);
8239 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8241 IDirect3DSurface9_Release(surface2);
8242 IDirect3DSurface9_Release(surface);
8243 IDirect3DCubeTexture9_Release(cube_texture);
8246 refcount = IDirect3DDevice9_Release(device);
8247 ok(!refcount, "Device has %u references left.\n", refcount);
8249 /* Backbuffer created with D3DFMT_UNKNOWN format. */
8250 device_desc.width = 640;
8251 device_desc.height = 480;
8252 device_desc.device_window = window;
8253 device_desc.flags = CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT | CREATE_DEVICE_LOCKABLE_BACKBUFFER;
8255 device = create_device(d3d, window, &device_desc);
8256 ok(!!device, "Failed to create device.\n");
8258 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8259 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
8261 dc = NULL;
8262 hr = IDirect3DSurface9_GetDC(surface, &dc);
8263 ok(!!dc, "Unexpected DC returned.\n");
8264 ok(SUCCEEDED(hr), "Failed to get backbuffer DC, hr %#x.\n", hr);
8265 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8266 ok(SUCCEEDED(hr), "Failed to release backbuffer DC, hr %#x.\n", hr);
8268 IDirect3DSurface9_Release(surface);
8270 refcount = IDirect3DDevice9_Release(device);
8271 ok(!refcount, "Device has %u references left.\n", refcount);
8273 IDirect3D9_Release(d3d);
8274 DestroyWindow(window);
8277 static void test_surface_dimensions(void)
8279 IDirect3DSurface9 *surface;
8280 IDirect3DDevice9 *device;
8281 IDirect3D9 *d3d;
8282 ULONG refcount;
8283 HWND window;
8284 HRESULT hr;
8286 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8287 0, 0, 640, 480, 0, 0, 0, 0);
8288 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8289 ok(!!d3d, "Failed to create a D3D object.\n");
8290 if (!(device = create_device(d3d, window, NULL)))
8292 skip("Failed to create a D3D device, skipping tests.\n");
8293 IDirect3D9_Release(d3d);
8294 DestroyWindow(window);
8295 return;
8298 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8299 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8300 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8301 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8302 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8303 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8305 refcount = IDirect3DDevice9_Release(device);
8306 ok(!refcount, "Device has %u references left.\n", refcount);
8307 IDirect3D9_Release(d3d);
8308 DestroyWindow(window);
8311 static void test_surface_format_null(void)
8313 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8314 IDirect3DTexture9 *texture;
8315 IDirect3DSurface9 *surface;
8316 IDirect3DSurface9 *rt, *ds;
8317 D3DLOCKED_RECT locked_rect;
8318 IDirect3DDevice9 *device;
8319 D3DSURFACE_DESC desc;
8320 IDirect3D9 *d3d;
8321 ULONG refcount;
8322 HWND window;
8323 HRESULT hr;
8325 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8326 ok(!!d3d, "Failed to create a D3D object.\n");
8328 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8329 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8330 if (hr != D3D_OK)
8332 skip("No D3DFMT_NULL support, skipping test.\n");
8333 IDirect3D9_Release(d3d);
8334 return;
8337 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8338 0, 0, 640, 480, 0, 0, 0, 0);
8339 if (!(device = create_device(d3d, window, NULL)))
8341 skip("Failed to create a D3D device, skipping tests.\n");
8342 IDirect3D9_Release(d3d);
8343 DestroyWindow(window);
8344 return;
8347 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8348 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8349 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8351 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8352 D3DFMT_NULL, D3DFMT_D24S8);
8353 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8355 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8356 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8357 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8359 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8360 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8362 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8363 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8365 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8366 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8368 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8369 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8371 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8372 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8374 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8375 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8377 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8378 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8380 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8381 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8383 IDirect3DSurface9_Release(rt);
8384 IDirect3DSurface9_Release(ds);
8386 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8387 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8388 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8389 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8391 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8392 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8393 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8394 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8396 hr = IDirect3DSurface9_UnlockRect(surface);
8397 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8399 IDirect3DSurface9_Release(surface);
8401 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8402 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8403 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8404 IDirect3DTexture9_Release(texture);
8406 refcount = IDirect3DDevice9_Release(device);
8407 ok(!refcount, "Device has %u references left.\n", refcount);
8408 IDirect3D9_Release(d3d);
8409 DestroyWindow(window);
8412 static void test_surface_double_unlock(void)
8414 static const D3DPOOL pools[] =
8416 D3DPOOL_DEFAULT,
8417 D3DPOOL_SCRATCH,
8418 D3DPOOL_SYSTEMMEM,
8420 IDirect3DSurface9 *surface;
8421 IDirect3DDevice9 *device;
8422 D3DLOCKED_RECT lr;
8423 IDirect3D9 *d3d;
8424 unsigned int i;
8425 ULONG refcount;
8426 HWND window;
8427 HRESULT hr;
8429 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8430 0, 0, 640, 480, 0, 0, 0, 0);
8431 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8432 ok(!!d3d, "Failed to create a D3D object.\n");
8433 if (!(device = create_device(d3d, window, NULL)))
8435 skip("Failed to create a D3D device, skipping tests.\n");
8436 IDirect3D9_Release(d3d);
8437 DestroyWindow(window);
8438 return;
8441 for (i = 0; i < ARRAY_SIZE(pools); ++i)
8443 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8444 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8445 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8447 hr = IDirect3DSurface9_UnlockRect(surface);
8448 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8449 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8450 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8451 hr = IDirect3DSurface9_UnlockRect(surface);
8452 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8453 hr = IDirect3DSurface9_UnlockRect(surface);
8454 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8456 IDirect3DSurface9_Release(surface);
8459 refcount = IDirect3DDevice9_Release(device);
8460 ok(!refcount, "Device has %u references left.\n", refcount);
8461 IDirect3D9_Release(d3d);
8462 DestroyWindow(window);
8465 static void test_surface_blocks(void)
8467 static const struct
8469 D3DFORMAT fmt;
8470 const char *name;
8471 unsigned int block_width;
8472 unsigned int block_height;
8473 BOOL broken;
8474 BOOL create_size_checked, core_fmt;
8476 formats[] =
8478 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8479 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8480 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8481 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8482 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8483 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8484 * which doesn't match the format spec. On newer Nvidia cards
8485 * they have the correct 4x4 block size */
8486 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8487 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8488 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8489 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8491 static const struct
8493 D3DPOOL pool;
8494 const char *name;
8495 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8496 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8497 BOOL success;
8499 pools[] =
8501 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8502 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8503 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8504 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8506 static struct
8508 D3DRESOURCETYPE rtype;
8509 const char *type_name;
8510 D3DPOOL pool;
8511 const char *pool_name;
8512 BOOL need_driver_support, need_runtime_support;
8514 create_tests[] =
8516 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8517 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8518 /* Managed offscreen plain surfaces are not supported */
8519 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8521 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8522 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8523 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8524 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8526 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8527 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8528 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8529 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8531 IDirect3DTexture9 *texture;
8532 IDirect3DCubeTexture9 *cube_texture;
8533 IDirect3DSurface9 *surface;
8534 D3DLOCKED_RECT locked_rect;
8535 IDirect3DDevice9 *device;
8536 unsigned int i, j, k, w, h;
8537 BOOL surface_only;
8538 IDirect3D9 *d3d;
8539 ULONG refcount;
8540 HWND window;
8541 HRESULT hr;
8542 RECT rect;
8543 BOOL tex_pow2, cube_pow2;
8544 D3DCAPS9 caps;
8545 static const RECT invalid[] =
8547 {60, 60, 60, 68}, /* 0 height */
8548 {60, 60, 68, 60}, /* 0 width */
8549 {68, 60, 60, 68}, /* left > right */
8550 {60, 68, 68, 60}, /* top > bottom */
8551 {-8, 60, 0, 68}, /* left < surface */
8552 {60, -8, 68, 0}, /* top < surface */
8553 {-16, 60, -8, 68}, /* right < surface */
8554 {60, -16, 68, -8}, /* bottom < surface */
8555 {60, 60, 136, 68}, /* right > surface */
8556 {60, 60, 68, 136}, /* bottom > surface */
8557 {136, 60, 144, 68}, /* left > surface */
8558 {60, 136, 68, 144}, /* top > surface */
8561 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8562 0, 0, 640, 480, 0, 0, 0, 0);
8563 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8564 ok(!!d3d, "Failed to create a D3D object.\n");
8565 if (!(device = create_device(d3d, window, NULL)))
8567 skip("Failed to create a D3D device, skipping tests.\n");
8568 IDirect3D9_Release(d3d);
8569 DestroyWindow(window);
8570 return;
8573 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8574 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8575 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8576 if (tex_pow2)
8577 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8578 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8580 for (i = 0; i < ARRAY_SIZE(formats); ++i)
8582 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8584 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8585 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8586 tex_support = SUCCEEDED(hr);
8587 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8588 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8589 cube_support = SUCCEEDED(hr);
8590 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8591 0, D3DRTYPE_SURFACE, formats[i].fmt);
8592 surface_support = SUCCEEDED(hr);
8594 /* Scratch pool in general allows texture creation even if the driver does
8595 * not support the format. If the format is an extension format that is not
8596 * known to the runtime, like ATI2N, some driver support is required for
8597 * this to work.
8599 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8600 * about ATI2N. I cannot check this because all my Vista+ machines support
8601 * ATI2N in hardware, but none of my WinXP machines do. */
8602 format_known = tex_support || cube_support || surface_support;
8604 for (w = 1; w <= 8; w++)
8606 for (h = 1; h <= 8; h++)
8608 BOOL block_aligned = TRUE;
8609 BOOL size_is_pow2;
8611 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8612 block_aligned = FALSE;
8614 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8616 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
8618 BOOL support, pow2;
8619 HRESULT expect_hr;
8620 BOOL may_succeed = FALSE;
8621 IUnknown **check_null;
8623 if (!formats[i].core_fmt)
8625 /* AMD warns against creating ATI2N textures smaller than
8626 * the block size because the runtime cannot calculate the
8627 * correct texture size. Generalize this for all extension
8628 * formats. */
8629 if (w < formats[i].block_width || h < formats[i].block_height)
8630 continue;
8633 texture = (IDirect3DTexture9 *)0xdeadbeef;
8634 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8635 surface = (IDirect3DSurface9 *)0xdeadbeef;
8637 switch (create_tests[j].rtype)
8639 case D3DRTYPE_TEXTURE:
8640 check_null = (IUnknown **)&texture;
8641 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8642 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8643 support = tex_support;
8644 pow2 = tex_pow2;
8645 break;
8647 case D3DRTYPE_CUBETEXTURE:
8648 if (w != h)
8649 continue;
8650 check_null = (IUnknown **)&cube_texture;
8651 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8652 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8653 support = cube_support;
8654 pow2 = cube_pow2;
8655 break;
8657 case D3DRTYPE_SURFACE:
8658 check_null = (IUnknown **)&surface;
8659 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8660 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8661 support = surface_support;
8662 pow2 = FALSE;
8663 break;
8665 default:
8666 check_null = NULL;
8667 pow2 = FALSE;
8668 support = FALSE;
8669 break;
8672 if (create_tests[j].need_driver_support && !support)
8673 expect_hr = D3DERR_INVALIDCALL;
8674 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8675 expect_hr = D3DERR_INVALIDCALL;
8676 else if (formats[i].create_size_checked && !block_aligned)
8677 expect_hr = D3DERR_INVALIDCALL;
8678 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8679 expect_hr = D3DERR_INVALIDCALL;
8680 else
8681 expect_hr = D3D_OK;
8683 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8684 * does not support it. Accept scratch creation of extension formats on
8685 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8686 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8687 * support it. */
8688 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8689 may_succeed = TRUE;
8691 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8692 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8693 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8694 if (FAILED(hr))
8695 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8696 else
8697 IUnknown_Release(*check_null);
8702 surface_only = FALSE;
8703 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8704 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8705 dynamic_tex_support = SUCCEEDED(hr);
8706 if (!dynamic_tex_support)
8708 if (!surface_support)
8710 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8711 continue;
8713 surface_only = TRUE;
8716 for (j = 0; j < ARRAY_SIZE(pools); ++j)
8718 switch (pools[j].pool)
8720 case D3DPOOL_SYSTEMMEM:
8721 case D3DPOOL_MANAGED:
8722 if (surface_only)
8723 continue;
8724 /* Fall through */
8725 case D3DPOOL_DEFAULT:
8726 if (surface_only)
8728 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8729 formats[i].fmt, pools[j].pool, &surface, NULL);
8730 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8732 else
8734 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8735 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8736 formats[i].fmt, pools[j].pool, &texture, NULL);
8737 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8738 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8739 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8740 IDirect3DTexture9_Release(texture);
8742 break;
8744 case D3DPOOL_SCRATCH:
8745 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8746 formats[i].fmt, pools[j].pool, &surface, NULL);
8747 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8748 break;
8750 default:
8751 break;
8754 if (formats[i].block_width > 1)
8756 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8757 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8758 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8759 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8760 SUCCEEDED(hr) ? "succeeded" : "failed",
8761 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8762 if (SUCCEEDED(hr))
8764 hr = IDirect3DSurface9_UnlockRect(surface);
8765 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8768 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8769 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8770 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8771 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8772 SUCCEEDED(hr) ? "succeeded" : "failed",
8773 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8774 if (SUCCEEDED(hr))
8776 hr = IDirect3DSurface9_UnlockRect(surface);
8777 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8781 if (formats[i].block_height > 1)
8783 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
8784 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8785 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8786 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8787 SUCCEEDED(hr) ? "succeeded" : "failed",
8788 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8789 if (SUCCEEDED(hr))
8791 hr = IDirect3DSurface9_UnlockRect(surface);
8792 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8795 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
8796 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8797 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8798 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8799 SUCCEEDED(hr) ? "succeeded" : "failed",
8800 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8801 if (SUCCEEDED(hr))
8803 hr = IDirect3DSurface9_UnlockRect(surface);
8804 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8808 for (k = 0; k < ARRAY_SIZE(invalid); ++k)
8810 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
8811 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
8812 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
8813 formats[i].name, pools[j].name, k);
8814 if (SUCCEEDED(hr))
8816 hr = IDirect3DSurface9_UnlockRect(surface);
8817 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8821 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8822 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8823 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
8824 hr = IDirect3DSurface9_UnlockRect(surface);
8825 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8827 IDirect3DSurface9_Release(surface);
8830 if (!dynamic_tex_support)
8832 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
8833 continue;
8836 if (formats[i].block_width == 1 && formats[i].block_height == 1)
8837 continue;
8838 if (!formats[i].core_fmt)
8839 continue;
8841 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
8842 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
8843 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
8845 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
8846 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8847 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8848 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8850 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
8851 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
8852 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8853 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8854 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8855 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8857 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8858 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8859 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8860 if (SUCCEEDED(hr))
8861 IDirect3DTexture9_UnlockRect(texture, 1);
8863 IDirect3DTexture9_Release(texture);
8866 refcount = IDirect3DDevice9_Release(device);
8867 ok(!refcount, "Device has %u references left.\n", refcount);
8868 IDirect3D9_Release(d3d);
8869 DestroyWindow(window);
8872 static void test_set_palette(void)
8874 IDirect3DDevice9 *device;
8875 IDirect3D9 *d3d9;
8876 UINT refcount;
8877 HWND window;
8878 HRESULT hr;
8879 PALETTEENTRY pal[256];
8880 unsigned int i;
8881 D3DCAPS9 caps;
8883 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8884 0, 0, 640, 480, 0, 0, 0, 0);
8885 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8886 ok(!!d3d9, "Failed to create a D3D object.\n");
8887 if (!(device = create_device(d3d9, window, NULL)))
8889 skip("Failed to create a D3D device, skipping tests.\n");
8890 DestroyWindow(window);
8891 return;
8894 for (i = 0; i < ARRAY_SIZE(pal); i++)
8896 pal[i].peRed = i;
8897 pal[i].peGreen = i;
8898 pal[i].peBlue = i;
8899 pal[i].peFlags = 0xff;
8901 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8902 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8904 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8905 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8906 for (i = 0; i < ARRAY_SIZE(pal); i++)
8908 pal[i].peRed = i;
8909 pal[i].peGreen = i;
8910 pal[i].peBlue = i;
8911 pal[i].peFlags = i;
8913 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
8915 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8916 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8918 else
8920 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8921 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
8924 refcount = IDirect3DDevice9_Release(device);
8925 ok(!refcount, "Device has %u references left.\n", refcount);
8926 IDirect3D9_Release(d3d9);
8927 DestroyWindow(window);
8930 static void test_swvp_buffer(void)
8932 IDirect3DDevice9 *device;
8933 IDirect3D9 *d3d9;
8934 UINT refcount;
8935 HWND window;
8936 HRESULT hr;
8937 unsigned int i;
8938 IDirect3DVertexBuffer9 *buffer;
8939 static const unsigned int bufsize = 1024;
8940 D3DVERTEXBUFFER_DESC desc;
8941 struct device_desc device_desc;
8942 struct
8944 float x, y, z;
8945 } *ptr, *ptr2;
8947 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8948 0, 0, 640, 480, 0, 0, 0, 0);
8949 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8950 ok(!!d3d9, "Failed to create a D3D object.\n");
8952 device_desc.device_window = window;
8953 device_desc.width = 640;
8954 device_desc.height = 480;
8955 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
8956 if (!(device = create_device(d3d9, window, &device_desc)))
8958 skip("Failed to create a D3D device, skipping tests.\n");
8959 DestroyWindow(window);
8960 IDirect3D9_Release(d3d9);
8961 return;
8964 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
8965 D3DPOOL_DEFAULT, &buffer, NULL);
8966 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8967 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8968 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8969 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
8970 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
8971 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
8973 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8974 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8975 for (i = 0; i < bufsize; i++)
8977 ptr[i].x = i * 1.0f;
8978 ptr[i].y = i * 2.0f;
8979 ptr[i].z = i * 3.0f;
8981 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8982 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8984 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8985 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8986 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8987 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8988 hr = IDirect3DDevice9_BeginScene(device);
8989 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8990 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8991 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8992 hr = IDirect3DDevice9_EndScene(device);
8993 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8995 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8996 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8997 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
8998 for (i = 0; i < bufsize; i++)
9000 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9002 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
9003 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9004 break;
9007 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9008 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9010 IDirect3DVertexBuffer9_Release(buffer);
9011 refcount = IDirect3DDevice9_Release(device);
9012 ok(!refcount, "Device has %u references left.\n", refcount);
9013 IDirect3D9_Release(d3d9);
9014 DestroyWindow(window);
9017 static void test_managed_buffer(void)
9019 static const unsigned int vertex_count = 1024;
9020 IDirect3DVertexBuffer9 *buffer;
9021 D3DVERTEXBUFFER_DESC desc;
9022 IDirect3DDevice9 *device;
9023 struct vec3 *ptr, *ptr2;
9024 IDirect3D9 *d3d9;
9025 unsigned int i;
9026 UINT refcount;
9027 HWND window;
9028 HRESULT hr;
9030 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9031 0, 0, 640, 480, 0, 0, 0, 0);
9032 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9033 ok(!!d3d9, "Failed to create a D3D object.\n");
9034 if (!(device = create_device(d3d9, window, NULL)))
9036 skip("Failed to create a D3D device, skipping tests.\n");
9037 IDirect3D9_Release(d3d9);
9038 DestroyWindow(window);
9039 return;
9042 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
9043 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
9044 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9045 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9046 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9047 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
9048 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
9050 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9051 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9052 for (i = 0; i < vertex_count; ++i)
9054 ptr[i].x = i * 1.0f;
9055 ptr[i].y = i * 2.0f;
9056 ptr[i].z = i * 3.0f;
9058 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9059 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9061 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9062 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9063 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9064 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9065 hr = IDirect3DDevice9_BeginScene(device);
9066 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9067 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9068 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9069 hr = IDirect3DDevice9_EndScene(device);
9070 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9072 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9073 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9074 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
9075 for (i = 0; i < vertex_count; ++i)
9077 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9079 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
9080 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9081 break;
9084 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9085 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9087 IDirect3DVertexBuffer9_Release(buffer);
9088 refcount = IDirect3DDevice9_Release(device);
9089 ok(!refcount, "Device has %u references left.\n", refcount);
9090 IDirect3D9_Release(d3d9);
9091 DestroyWindow(window);
9094 static void test_npot_textures(void)
9096 IDirect3DDevice9 *device = NULL;
9097 IDirect3D9 *d3d9;
9098 ULONG refcount;
9099 HWND window = NULL;
9100 HRESULT hr;
9101 D3DCAPS9 caps;
9102 IDirect3DTexture9 *texture;
9103 IDirect3DCubeTexture9 *cube_texture;
9104 IDirect3DVolumeTexture9 *volume_texture;
9105 struct
9107 D3DPOOL pool;
9108 const char *pool_name;
9109 HRESULT hr;
9111 pools[] =
9113 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
9114 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
9115 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
9116 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
9118 unsigned int i, levels;
9119 BOOL tex_pow2, cube_pow2, vol_pow2;
9121 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9122 0, 0, 640, 480, 0, 0, 0, 0);
9123 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9124 ok(!!d3d9, "Failed to create a D3D object.\n");
9125 if (!(device = create_device(d3d9, window, NULL)))
9127 skip("Failed to create a D3D device, skipping tests.\n");
9128 goto done;
9131 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9132 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9133 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
9134 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
9135 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9136 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
9137 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
9139 for (i = 0; i < ARRAY_SIZE(pools); i++)
9141 for (levels = 0; levels <= 2; levels++)
9143 HRESULT expected;
9145 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
9146 pools[i].pool, &texture, NULL);
9147 if (!tex_pow2)
9149 expected = D3D_OK;
9151 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
9153 if (levels == 1)
9154 expected = D3D_OK;
9155 else
9156 expected = pools[i].hr;
9158 else
9160 expected = pools[i].hr;
9162 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
9163 pools[i].pool_name, levels, hr, expected);
9165 if (SUCCEEDED(hr))
9166 IDirect3DTexture9_Release(texture);
9169 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9170 &cube_texture, NULL);
9171 if (tex_pow2)
9173 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9174 pools[i].pool_name, hr, pools[i].hr);
9176 else
9178 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9179 pools[i].pool_name, hr, D3D_OK);
9182 if (SUCCEEDED(hr))
9183 IDirect3DCubeTexture9_Release(cube_texture);
9185 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9186 &volume_texture, NULL);
9187 if (tex_pow2)
9189 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9190 pools[i].pool_name, hr, pools[i].hr);
9192 else
9194 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9195 pools[i].pool_name, hr, D3D_OK);
9198 if (SUCCEEDED(hr))
9199 IDirect3DVolumeTexture9_Release(volume_texture);
9202 done:
9203 if (device)
9205 refcount = IDirect3DDevice9_Release(device);
9206 ok(!refcount, "Device has %u references left.\n", refcount);
9208 IDirect3D9_Release(d3d9);
9209 DestroyWindow(window);
9213 static void test_vidmem_accounting(void)
9215 IDirect3DDevice9 *device;
9216 IDirect3D9 *d3d9;
9217 ULONG refcount;
9218 HWND window;
9219 HRESULT hr = D3D_OK;
9220 IDirect3DTexture9 *textures[20];
9221 unsigned int i;
9222 UINT vidmem_start, vidmem_end, diff;
9224 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9225 0, 0, 640, 480, 0, 0, 0, 0);
9226 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9227 ok(!!d3d9, "Failed to create a D3D object.\n");
9228 if (!(device = create_device(d3d9, window, NULL)))
9230 skip("Failed to create a D3D device, skipping tests.\n");
9231 IDirect3D9_Release(d3d9);
9232 DestroyWindow(window);
9233 return;
9236 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
9237 memset(textures, 0, sizeof(textures));
9238 for (i = 0; i < ARRAY_SIZE(textures); i++)
9240 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9241 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9242 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9243 * E_FAIL is returned on address space or system memory exhaustion */
9244 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9245 "Failed to create texture, hr %#x.\n", hr);
9247 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9249 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9250 diff = vidmem_start - vidmem_end;
9251 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9252 2 * i, diff / 1024 / 1024);
9254 for (i = 0; i < ARRAY_SIZE(textures); i++)
9256 if (textures[i])
9257 IDirect3DTexture9_Release(textures[i]);
9260 refcount = IDirect3DDevice9_Release(device);
9261 ok(!refcount, "Device has %u references left.\n", refcount);
9262 IDirect3D9_Release(d3d9);
9263 DestroyWindow(window);
9266 static void test_volume_locking(void)
9268 IDirect3DDevice9 *device;
9269 IDirect3D9 *d3d9;
9270 HWND window;
9271 HRESULT hr;
9272 IDirect3DVolumeTexture9 *texture;
9273 unsigned int i;
9274 D3DLOCKED_BOX locked_box;
9275 ULONG refcount;
9276 D3DCAPS9 caps;
9277 static const struct
9279 D3DPOOL pool;
9280 DWORD usage;
9281 HRESULT create_hr, lock_hr;
9283 tests[] =
9285 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9286 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9287 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9288 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9289 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9290 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9291 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9292 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9295 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9296 0, 0, 640, 480, 0, 0, 0, 0);
9297 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9298 ok(!!d3d9, "Failed to create a D3D object.\n");
9299 if (!(device = create_device(d3d9, window, NULL)))
9301 skip("Failed to create a D3D device, skipping tests.\n");
9302 IDirect3D9_Release(d3d9);
9303 DestroyWindow(window);
9304 return;
9307 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9308 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9309 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9311 skip("Volume textures not supported, skipping test.\n");
9312 goto out;
9315 for (i = 0; i < ARRAY_SIZE(tests); i++)
9317 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9318 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9319 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9320 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9321 if (FAILED(hr))
9322 continue;
9324 locked_box.pBits = (void *)0xdeadbeef;
9325 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9326 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9327 if (SUCCEEDED(hr))
9329 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9330 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9332 else
9334 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9336 IDirect3DVolumeTexture9_Release(texture);
9339 out:
9340 refcount = IDirect3DDevice9_Release(device);
9341 ok(!refcount, "Device has %u references left.\n", refcount);
9342 IDirect3D9_Release(d3d9);
9343 DestroyWindow(window);
9346 static void test_update_volumetexture(void)
9348 IDirect3DDevice9 *device;
9349 IDirect3D9 *d3d9;
9350 HWND window;
9351 HRESULT hr;
9352 IDirect3DVolumeTexture9 *src, *dst;
9353 unsigned int i;
9354 D3DLOCKED_BOX locked_box;
9355 ULONG refcount;
9356 D3DCAPS9 caps;
9357 static const struct
9359 D3DPOOL src_pool, dst_pool;
9360 HRESULT hr;
9362 tests[] =
9364 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9365 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9366 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9367 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9369 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9370 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9371 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9372 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9374 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9375 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9376 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9377 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9379 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9380 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9381 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9382 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9384 static const struct
9386 UINT src_size, dst_size;
9387 UINT src_lvl, dst_lvl;
9388 D3DFORMAT src_fmt, dst_fmt;
9390 tests2[] =
9392 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9393 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9394 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9395 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9396 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9397 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9398 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9399 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9402 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9403 0, 0, 640, 480, 0, 0, 0, 0);
9404 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9405 ok(!!d3d9, "Failed to create a D3D object.\n");
9406 if (!(device = create_device(d3d9, window, NULL)))
9408 skip("Failed to create a D3D device, skipping tests.\n");
9409 IDirect3D9_Release(d3d9);
9410 DestroyWindow(window);
9411 return;
9414 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9415 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9416 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9418 skip("Volume textures not supported, skipping test.\n");
9419 goto out;
9422 for (i = 0; i < ARRAY_SIZE(tests); i++)
9424 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9425 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9427 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9428 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9429 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9430 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9431 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9432 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9434 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9435 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9436 *((DWORD *)locked_box.pBits) = 0x11223344;
9437 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9438 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9440 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9441 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9442 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9444 if (SUCCEEDED(hr))
9446 DWORD content = *((DWORD *)locked_box.pBits);
9447 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9448 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9449 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9450 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9451 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9453 IDirect3DVolumeTexture9_Release(src);
9454 IDirect3DVolumeTexture9_Release(dst);
9457 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9459 skip("Mipmapped volume maps not supported.\n");
9460 goto out;
9463 for (i = 0; i < ARRAY_SIZE(tests2); i++)
9465 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9466 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9467 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9468 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9469 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9470 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9471 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9472 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9474 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9475 todo_wine_if (FAILED(hr))
9476 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9478 IDirect3DVolumeTexture9_Release(src);
9479 IDirect3DVolumeTexture9_Release(dst);
9482 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9483 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9484 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9485 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9486 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9488 * I'm not adding tests for this behavior until an application needs it. */
9490 out:
9491 refcount = IDirect3DDevice9_Release(device);
9492 ok(!refcount, "Device has %u references left.\n", refcount);
9493 IDirect3D9_Release(d3d9);
9494 DestroyWindow(window);
9497 static void test_create_rt_ds_fail(void)
9499 IDirect3DDevice9 *device;
9500 HWND window;
9501 HRESULT hr;
9502 ULONG refcount;
9503 IDirect3D9 *d3d9;
9504 IDirect3DSurface9 *surface;
9506 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9507 0, 0, 640, 480, 0, 0, 0, 0);
9508 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9509 ok(!!d3d9, "Failed to create a D3D object.\n");
9510 if (!(device = create_device(d3d9, window, NULL)))
9512 skip("Failed to create a D3D device, skipping tests.\n");
9513 IDirect3D9_Release(d3d9);
9514 DestroyWindow(window);
9515 return;
9518 /* Output pointer == NULL segfaults on Windows. */
9520 surface = (IDirect3DSurface9 *)0xdeadbeef;
9521 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9522 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9523 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9524 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9525 if (SUCCEEDED(hr))
9526 IDirect3DSurface9_Release(surface);
9528 surface = (IDirect3DSurface9 *)0xdeadbeef;
9529 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9530 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9531 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9532 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9533 if (SUCCEEDED(hr))
9534 IDirect3DSurface9_Release(surface);
9536 refcount = IDirect3DDevice9_Release(device);
9537 ok(!refcount, "Device has %u references left.\n", refcount);
9538 IDirect3D9_Release(d3d9);
9539 DestroyWindow(window);
9542 static void test_volume_blocks(void)
9544 IDirect3DDevice9 *device;
9545 IDirect3D9 *d3d9;
9546 UINT refcount;
9547 HWND window;
9548 HRESULT hr;
9549 D3DCAPS9 caps;
9550 IDirect3DVolumeTexture9 *texture;
9551 unsigned int w, h, d, i, j;
9552 static const struct
9554 D3DFORMAT fmt;
9555 const char *name;
9556 unsigned int block_width;
9557 unsigned int block_height;
9558 unsigned int block_depth;
9559 unsigned int block_size;
9560 unsigned int broken;
9561 BOOL create_size_checked, core_fmt;
9563 formats[] =
9565 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9566 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9567 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9568 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9569 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9570 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9571 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9572 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9573 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9574 * which doesn't match the format spec. On newer Nvidia cards
9575 * it has the correct 4x4 block size.
9576 * ATI1N volume textures are only supported by AMD GPUs right
9577 * now and locking offsets seem just wrong. */
9578 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9579 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9580 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9581 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9583 static const struct
9585 D3DPOOL pool;
9586 const char *name;
9587 BOOL need_driver_support, need_runtime_support;
9589 create_tests[] =
9591 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9592 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9593 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9594 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9596 static const struct
9598 unsigned int x, y, z, x2, y2, z2;
9600 offset_tests[] =
9602 {0, 0, 0, 8, 8, 8},
9603 {0, 0, 3, 8, 8, 8},
9604 {0, 4, 0, 8, 8, 8},
9605 {0, 4, 3, 8, 8, 8},
9606 {4, 0, 0, 8, 8, 8},
9607 {4, 0, 3, 8, 8, 8},
9608 {4, 4, 0, 8, 8, 8},
9609 {4, 4, 3, 8, 8, 8},
9611 D3DBOX box;
9612 D3DLOCKED_BOX locked_box;
9613 BYTE *base;
9614 INT expected_row_pitch, expected_slice_pitch;
9615 BOOL support;
9616 BOOL pow2;
9617 unsigned int offset, expected_offset;
9619 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9620 0, 0, 640, 480, 0, 0, 0, 0);
9621 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9622 ok(!!d3d9, "Failed to create a D3D object.\n");
9623 if (!(device = create_device(d3d9, window, NULL)))
9625 skip("Failed to create a D3D device, skipping tests.\n");
9626 IDirect3D9_Release(d3d9);
9627 DestroyWindow(window);
9628 return;
9630 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9631 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9632 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9634 for (i = 0; i < ARRAY_SIZE(formats); i++)
9636 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9637 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9638 support = SUCCEEDED(hr);
9640 /* Test creation restrictions */
9641 for (w = 1; w <= 8; w++)
9643 for (h = 1; h <= 8; h++)
9645 for (d = 1; d <= 8; d++)
9647 HRESULT expect_hr;
9648 BOOL size_is_pow2;
9649 BOOL block_aligned = TRUE;
9651 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9652 block_aligned = FALSE;
9654 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9656 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
9658 BOOL may_succeed = FALSE;
9660 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9661 expect_hr = D3DERR_INVALIDCALL;
9662 else if (formats[i].create_size_checked && !block_aligned)
9663 expect_hr = D3DERR_INVALIDCALL;
9664 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9665 expect_hr = D3DERR_INVALIDCALL;
9666 else if (create_tests[j].need_driver_support && !support)
9667 expect_hr = D3DERR_INVALIDCALL;
9668 else
9669 expect_hr = D3D_OK;
9671 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9672 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9673 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9675 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9676 * does not support it. Accept scratch creation of extension formats on
9677 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9678 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9679 * support it. */
9680 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9681 may_succeed = TRUE;
9683 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9684 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9685 hr, formats[i].name, create_tests[j].name, w, h, d);
9687 if (FAILED(hr))
9688 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9689 else
9690 IDirect3DVolumeTexture9_Release(texture);
9696 if (!support && !formats[i].core_fmt)
9697 continue;
9699 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9700 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9701 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9703 /* Test lockrect offset */
9704 for (j = 0; j < ARRAY_SIZE(offset_tests); j++)
9706 unsigned int bytes_per_pixel;
9707 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9709 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9710 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9712 base = locked_box.pBits;
9713 if (formats[i].broken == 1)
9715 expected_row_pitch = bytes_per_pixel * 24;
9717 else if (formats[i].broken == 2)
9719 expected_row_pitch = 24;
9721 else
9723 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9724 * formats[i].block_size;
9726 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9727 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9729 if (formats[i].broken)
9731 expected_slice_pitch = expected_row_pitch * 8;
9733 else
9735 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9736 * expected_row_pitch;
9738 ok(locked_box.SlicePitch == expected_slice_pitch,
9739 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9740 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9742 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9743 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9745 box.Left = offset_tests[j].x;
9746 box.Top = offset_tests[j].y;
9747 box.Front = offset_tests[j].z;
9748 box.Right = offset_tests[j].x2;
9749 box.Bottom = offset_tests[j].y2;
9750 box.Back = offset_tests[j].z2;
9751 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9752 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9754 offset = (BYTE *)locked_box.pBits - base;
9755 if (formats[i].broken == 1)
9757 expected_offset = box.Front * expected_slice_pitch
9758 + box.Top * expected_row_pitch
9759 + box.Left * bytes_per_pixel;
9761 else if (formats[i].broken == 2)
9763 expected_offset = box.Front * expected_slice_pitch
9764 + box.Top * expected_row_pitch
9765 + box.Left;
9767 else
9769 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9770 + (box.Top / formats[i].block_height) * expected_row_pitch
9771 + (box.Left / formats[i].block_width) * formats[i].block_size;
9773 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9774 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9776 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9777 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9780 /* Test partial block locks */
9781 box.Front = 0;
9782 box.Back = 1;
9783 if (formats[i].block_width > 1)
9785 box.Left = formats[i].block_width >> 1;
9786 box.Top = 0;
9787 box.Right = formats[i].block_width;
9788 box.Bottom = formats[i].block_height;
9789 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9790 ok(FAILED(hr) || broken(formats[i].broken),
9791 "Partial block lock succeeded, expected failure, format %s.\n",
9792 formats[i].name);
9793 if (SUCCEEDED(hr))
9795 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9796 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9799 box.Left = 0;
9800 box.Top = 0;
9801 box.Right = formats[i].block_width >> 1;
9802 box.Bottom = formats[i].block_height;
9803 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9804 ok(FAILED(hr) || broken(formats[i].broken),
9805 "Partial block lock succeeded, expected failure, format %s.\n",
9806 formats[i].name);
9807 if (SUCCEEDED(hr))
9809 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9810 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9814 if (formats[i].block_height > 1)
9816 box.Left = 0;
9817 box.Top = formats[i].block_height >> 1;
9818 box.Right = formats[i].block_width;
9819 box.Bottom = formats[i].block_height;
9820 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9821 ok(FAILED(hr) || broken(formats[i].broken),
9822 "Partial block lock succeeded, expected failure, format %s.\n",
9823 formats[i].name);
9824 if (SUCCEEDED(hr))
9826 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9827 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9830 box.Left = 0;
9831 box.Top = 0;
9832 box.Right = formats[i].block_width;
9833 box.Bottom = formats[i].block_height >> 1;
9834 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9835 ok(FAILED(hr) || broken(formats[i].broken),
9836 "Partial block lock succeeded, expected failure, format %s.\n",
9837 formats[i].name);
9838 if (SUCCEEDED(hr))
9840 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9841 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9845 /* Test full block lock */
9846 box.Left = 0;
9847 box.Top = 0;
9848 box.Right = formats[i].block_width;
9849 box.Bottom = formats[i].block_height;
9850 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9851 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9852 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9853 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9855 IDirect3DVolumeTexture9_Release(texture);
9857 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
9858 * does not allocate surfaces smaller than the blocksize properly. */
9859 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
9861 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
9862 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9863 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9865 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
9866 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9867 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9868 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9870 box.Left = box.Top = box.Front = 0;
9871 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
9872 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
9873 box.Back = 1;
9874 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9875 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9876 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9877 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9879 box.Right = formats[i].block_width;
9880 box.Bottom = formats[i].block_height;
9881 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9882 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9883 if (SUCCEEDED(hr))
9884 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9886 IDirect3DVolumeTexture9_Release(texture);
9890 refcount = IDirect3DDevice9_Release(device);
9891 ok(!refcount, "Device has %u references left.\n", refcount);
9892 IDirect3D9_Release(d3d9);
9893 DestroyWindow(window);
9896 static void test_lockbox_invalid(void)
9898 static const struct
9900 D3DBOX box;
9901 HRESULT result;
9903 test_data[] =
9905 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
9906 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
9907 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
9908 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
9909 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
9910 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
9911 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
9912 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
9913 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
9914 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
9915 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
9916 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
9917 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
9918 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
9920 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
9921 IDirect3DVolumeTexture9 *texture = NULL;
9922 D3DLOCKED_BOX locked_box;
9923 IDirect3DDevice9 *device;
9924 IDirect3D9 *d3d;
9925 unsigned int i;
9926 ULONG refcount;
9927 HWND window;
9928 BYTE *base;
9929 HRESULT hr;
9931 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9932 0, 0, 640, 480, 0, 0, 0, 0);
9933 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9934 ok(!!d3d, "Failed to create a D3D object.\n");
9935 if (!(device = create_device(d3d, window, NULL)))
9937 skip("Failed to create a D3D device, skipping tests.\n");
9938 IDirect3D9_Release(d3d);
9939 DestroyWindow(window);
9940 return;
9943 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
9944 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
9945 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9946 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9947 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9948 base = locked_box.pBits;
9949 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9950 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9952 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9954 unsigned int offset, expected_offset;
9955 const D3DBOX *box = &test_data[i].box;
9957 locked_box.pBits = (BYTE *)0xdeadbeef;
9958 locked_box.RowPitch = 0xdeadbeef;
9959 locked_box.SlicePitch = 0xdeadbeef;
9961 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
9962 /* Unlike surfaces, volumes properly check the box even in Windows XP */
9963 ok(hr == test_data[i].result,
9964 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
9965 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
9966 test_data[i].result);
9967 if (FAILED(hr))
9968 continue;
9970 offset = (BYTE *)locked_box.pBits - base;
9971 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
9972 ok(offset == expected_offset,
9973 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
9974 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
9976 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9977 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9980 /* locked_box = NULL throws an exception on Windows */
9981 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9982 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9983 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9984 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9985 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9986 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9987 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9988 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9990 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9991 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9992 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9993 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9994 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9995 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9996 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9997 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9998 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
9999 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10000 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
10001 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
10002 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10003 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10005 IDirect3DVolumeTexture9_Release(texture);
10006 refcount = IDirect3DDevice9_Release(device);
10007 ok(!refcount, "Device has %u references left.\n", refcount);
10008 IDirect3D9_Release(d3d);
10009 DestroyWindow(window);
10012 static void test_shared_handle(void)
10014 IDirect3DDevice9 *device;
10015 IDirect3D9 *d3d;
10016 ULONG refcount;
10017 HWND window;
10018 HRESULT hr;
10019 /* Native d3d9ex refuses to create a shared texture if the texture pointer
10020 * is not initialized to NULL. Make sure this doesn't cause issues here. */
10021 IDirect3DTexture9 *texture = NULL;
10022 IDirect3DSurface9 *surface = NULL;
10023 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
10024 IDirect3DIndexBuffer9 *index_buffer = NULL;
10025 HANDLE handle = NULL;
10026 void *mem;
10027 D3DCAPS9 caps;
10029 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10030 0, 0, 640, 480, 0, 0, 0, 0);
10031 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10032 ok(!!d3d, "Failed to create a D3D object.\n");
10033 if (!(device = create_device(d3d, window, NULL)))
10035 skip("Failed to create a D3D device, skipping tests.\n");
10036 IDirect3D9_Release(d3d);
10037 DestroyWindow(window);
10038 return;
10041 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10042 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10043 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
10045 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
10046 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
10047 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10048 D3DPOOL_DEFAULT, &texture, &handle);
10049 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10050 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10051 D3DPOOL_SYSTEMMEM, &texture, &mem);
10052 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10054 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10055 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
10056 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10057 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10058 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
10059 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10061 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10062 &vertex_buffer, &handle);
10063 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10064 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10065 &vertex_buffer, &mem);
10066 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
10068 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10069 &index_buffer, &handle);
10070 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10071 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10072 &index_buffer, &mem);
10073 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10075 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10077 IDirect3DCubeTexture9 *cube_texture = NULL;
10078 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10079 D3DPOOL_DEFAULT, &cube_texture, &handle);
10080 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10081 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10082 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
10083 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10086 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
10088 IDirect3DVolumeTexture9 *volume_texture = NULL;
10089 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10090 D3DPOOL_DEFAULT, &volume_texture, &handle);
10091 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10092 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10093 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
10094 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10097 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
10098 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10099 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10101 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
10102 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10103 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10105 HeapFree(GetProcessHeap(), 0, mem);
10106 refcount = IDirect3DDevice9_Release(device);
10107 ok(!refcount, "Device has %u references left.\n", refcount);
10108 IDirect3D9_Release(d3d);
10109 DestroyWindow(window);
10112 static void test_pixel_format(void)
10114 HWND hwnd, hwnd2 = NULL;
10115 HDC hdc, hdc2 = NULL;
10116 HMODULE gl = NULL;
10117 int format, test_format;
10118 PIXELFORMATDESCRIPTOR pfd;
10119 IDirect3D9 *d3d9 = NULL;
10120 IDirect3DDevice9 *device = NULL;
10121 HRESULT hr;
10122 static const float point[3] = {0.0, 0.0, 0.0};
10124 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10125 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10126 if (!hwnd)
10128 skip("Failed to create window\n");
10129 return;
10132 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10133 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10135 hdc = GetDC(hwnd);
10136 if (!hdc)
10138 skip("Failed to get DC\n");
10139 goto cleanup;
10142 if (hwnd2)
10143 hdc2 = GetDC(hwnd2);
10145 gl = LoadLibraryA("opengl32.dll");
10146 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
10148 format = GetPixelFormat(hdc);
10149 ok(format == 0, "new window has pixel format %d\n", format);
10151 ZeroMemory(&pfd, sizeof(pfd));
10152 pfd.nSize = sizeof(pfd);
10153 pfd.nVersion = 1;
10154 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
10155 pfd.iPixelType = PFD_TYPE_RGBA;
10156 pfd.iLayerType = PFD_MAIN_PLANE;
10157 format = ChoosePixelFormat(hdc, &pfd);
10158 if (format <= 0)
10160 skip("no pixel format available\n");
10161 goto cleanup;
10164 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
10166 skip("failed to set pixel format\n");
10167 goto cleanup;
10170 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
10172 skip("failed to set pixel format on second window\n");
10173 if (hdc2)
10175 ReleaseDC(hwnd2, hdc2);
10176 hdc2 = NULL;
10180 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
10181 ok(!!d3d9, "Failed to create a D3D object.\n");
10183 test_format = GetPixelFormat(hdc);
10184 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10186 if (!(device = create_device(d3d9, hwnd, NULL)))
10188 skip("Failed to create device\n");
10189 goto cleanup;
10192 test_format = GetPixelFormat(hdc);
10193 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10195 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10196 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10198 test_format = GetPixelFormat(hdc);
10199 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10201 hr = IDirect3DDevice9_BeginScene(device);
10202 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
10204 test_format = GetPixelFormat(hdc);
10205 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10207 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
10208 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10210 test_format = GetPixelFormat(hdc);
10211 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10213 hr = IDirect3DDevice9_EndScene(device);
10214 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
10216 test_format = GetPixelFormat(hdc);
10217 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10219 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10220 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10222 test_format = GetPixelFormat(hdc);
10223 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10225 if (hdc2)
10227 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
10228 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10230 test_format = GetPixelFormat(hdc);
10231 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10233 test_format = GetPixelFormat(hdc2);
10234 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
10237 cleanup:
10238 if (device)
10240 UINT refcount = IDirect3DDevice9_Release(device);
10241 ok(!refcount, "Device has %u references left.\n", refcount);
10243 if (d3d9) IDirect3D9_Release(d3d9);
10244 if (gl) FreeLibrary(gl);
10245 if (hdc) ReleaseDC(hwnd, hdc);
10246 if (hdc2) ReleaseDC(hwnd2, hdc2);
10247 if (hwnd) DestroyWindow(hwnd);
10248 if (hwnd2) DestroyWindow(hwnd2);
10251 static void test_begin_end_state_block(void)
10253 IDirect3DStateBlock9 *stateblock;
10254 IDirect3DDevice9 *device;
10255 IDirect3D9 *d3d;
10256 ULONG refcount;
10257 HWND window;
10258 HRESULT hr;
10260 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10261 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10262 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10263 ok(!!d3d, "Failed to create a D3D object.\n");
10264 if (!(device = create_device(d3d, window, NULL)))
10266 skip("Failed to create a D3D device, skipping tests.\n");
10267 IDirect3D9_Release(d3d);
10268 DestroyWindow(window);
10269 return;
10272 /* Should succeed. */
10273 hr = IDirect3DDevice9_BeginStateBlock(device);
10274 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10276 /* Calling BeginStateBlock() while recording should return
10277 * D3DERR_INVALIDCALL. */
10278 hr = IDirect3DDevice9_BeginStateBlock(device);
10279 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10281 /* Should succeed. */
10282 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10283 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10284 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10285 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10286 "Got unexpected stateblock %p.\n", stateblock);
10287 IDirect3DStateBlock9_Release(stateblock);
10289 /* Calling EndStateBlock() while not recording should return
10290 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10291 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10292 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10293 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10294 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10295 "Got unexpected stateblock %p.\n", stateblock);
10297 refcount = IDirect3DDevice9_Release(device);
10298 ok(!refcount, "Device has %u references left.\n", refcount);
10299 IDirect3D9_Release(d3d);
10300 DestroyWindow(window);
10303 static void test_shader_constant_apply(void)
10305 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10306 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10307 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10308 IDirect3DStateBlock9 *stateblock;
10309 DWORD vs_version, ps_version;
10310 IDirect3DDevice9 *device;
10311 IDirect3D9 *d3d;
10312 ULONG refcount;
10313 D3DCAPS9 caps;
10314 float ret[4];
10315 HWND window;
10316 HRESULT hr;
10318 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10319 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10320 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10321 ok(!!d3d, "Failed to create a D3D object.\n");
10322 if (!(device = create_device(d3d, window, NULL)))
10324 skip("Failed to create a D3D device, skipping tests.\n");
10325 IDirect3D9_Release(d3d);
10326 DestroyWindow(window);
10327 return;
10330 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10331 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10332 vs_version = caps.VertexShaderVersion & 0xffff;
10333 ps_version = caps.PixelShaderVersion & 0xffff;
10335 if (vs_version)
10337 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10338 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10339 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10340 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10342 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10343 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10344 ok(!memcmp(ret, initial, sizeof(initial)),
10345 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10346 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10347 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10348 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10349 ok(!memcmp(ret, initial, sizeof(initial)),
10350 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10351 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10353 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10354 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10356 if (ps_version)
10358 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10359 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10360 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10361 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10363 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10364 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10365 ok(!memcmp(ret, initial, sizeof(initial)),
10366 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10367 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10368 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10369 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10370 ok(!memcmp(ret, initial, sizeof(initial)),
10371 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10372 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10374 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10375 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10378 hr = IDirect3DDevice9_BeginStateBlock(device);
10379 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10381 if (vs_version)
10383 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10384 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10386 if (ps_version)
10388 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10389 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10392 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10393 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10395 if (vs_version)
10397 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10398 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10399 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10400 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10401 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10402 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10403 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10404 ok(!memcmp(ret, initial, sizeof(initial)),
10405 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10406 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10408 if (ps_version)
10410 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10411 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10412 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10413 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10414 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10415 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10416 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10417 ok(!memcmp(ret, initial, sizeof(initial)),
10418 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10419 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10422 /* Apply doesn't overwrite constants that aren't explicitly set on the
10423 * source stateblock. */
10424 hr = IDirect3DStateBlock9_Apply(stateblock);
10425 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10427 if (vs_version)
10429 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10430 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10431 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10432 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10433 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10434 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10435 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10436 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10437 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10438 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10440 if (ps_version)
10442 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10443 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10444 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10445 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10446 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10447 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10448 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10449 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10450 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10451 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10454 IDirect3DStateBlock9_Release(stateblock);
10455 refcount = IDirect3DDevice9_Release(device);
10456 ok(!refcount, "Device has %u references left.\n", refcount);
10457 IDirect3D9_Release(d3d);
10458 DestroyWindow(window);
10461 static void test_vdecl_apply(void)
10463 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10464 IDirect3DStateBlock9 *stateblock;
10465 IDirect3DDevice9 *device;
10466 IDirect3D9 *d3d;
10467 ULONG refcount;
10468 HWND window;
10469 HRESULT hr;
10471 static const D3DVERTEXELEMENT9 decl1[] =
10473 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10474 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10475 D3DDECL_END(),
10478 static const D3DVERTEXELEMENT9 decl2[] =
10480 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10481 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10482 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10483 D3DDECL_END(),
10486 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10487 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10488 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10489 ok(!!d3d, "Failed to create a D3D object.\n");
10490 if (!(device = create_device(d3d, window, NULL)))
10492 skip("Failed to create a D3D device, skipping tests.\n");
10493 IDirect3D9_Release(d3d);
10494 DestroyWindow(window);
10495 return;
10498 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10499 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10501 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10502 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10504 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10505 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10506 hr = IDirect3DDevice9_BeginStateBlock(device);
10507 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10508 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10509 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10510 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10511 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10512 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10513 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10514 hr = IDirect3DStateBlock9_Apply(stateblock);
10515 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10516 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10517 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10518 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10519 declaration, declaration1);
10520 IDirect3DVertexDeclaration9_Release(declaration);
10522 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10523 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10524 hr = IDirect3DStateBlock9_Capture(stateblock);
10525 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10526 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10527 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10528 hr = IDirect3DStateBlock9_Apply(stateblock);
10529 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10530 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10531 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10532 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10533 declaration, declaration2);
10534 IDirect3DVertexDeclaration9_Release(declaration);
10536 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10537 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10538 hr = IDirect3DStateBlock9_Capture(stateblock);
10539 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10540 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10541 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10542 hr = IDirect3DStateBlock9_Apply(stateblock);
10543 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10544 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10545 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10546 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10547 declaration, declaration2);
10548 IDirect3DVertexDeclaration9_Release(declaration);
10550 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10551 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10552 hr = IDirect3DStateBlock9_Capture(stateblock);
10553 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10554 hr = IDirect3DStateBlock9_Apply(stateblock);
10555 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10556 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10557 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10558 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10560 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10561 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10562 hr = IDirect3DStateBlock9_Capture(stateblock);
10563 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10564 hr = IDirect3DStateBlock9_Apply(stateblock);
10565 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10566 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10567 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10568 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10569 declaration, declaration2);
10570 IDirect3DVertexDeclaration9_Release(declaration);
10572 IDirect3DStateBlock9_Release(stateblock);
10573 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10574 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10575 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10576 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10577 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10578 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10579 hr = IDirect3DStateBlock9_Apply(stateblock);
10580 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10581 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10582 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10583 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10584 declaration, declaration1);
10585 IDirect3DVertexDeclaration9_Release(declaration);
10587 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10588 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10589 hr = IDirect3DStateBlock9_Capture(stateblock);
10590 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10591 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10592 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10593 hr = IDirect3DStateBlock9_Apply(stateblock);
10594 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10595 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10596 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10597 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10598 declaration, declaration2);
10599 IDirect3DVertexDeclaration9_Release(declaration);
10601 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10602 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10603 hr = IDirect3DStateBlock9_Capture(stateblock);
10604 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10605 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10606 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10607 hr = IDirect3DStateBlock9_Apply(stateblock);
10608 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10609 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10610 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10611 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10612 declaration, declaration2);
10613 IDirect3DVertexDeclaration9_Release(declaration);
10615 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10616 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10617 hr = IDirect3DStateBlock9_Capture(stateblock);
10618 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10619 hr = IDirect3DStateBlock9_Apply(stateblock);
10620 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10621 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10622 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10623 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10625 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10626 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10627 hr = IDirect3DStateBlock9_Capture(stateblock);
10628 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10629 hr = IDirect3DStateBlock9_Apply(stateblock);
10630 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10631 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10632 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10633 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10634 declaration, declaration2);
10635 IDirect3DVertexDeclaration9_Release(declaration);
10637 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10638 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10639 IDirect3DVertexDeclaration9_Release(declaration1);
10640 IDirect3DVertexDeclaration9_Release(declaration2);
10641 IDirect3DStateBlock9_Release(stateblock);
10642 refcount = IDirect3DDevice9_Release(device);
10643 ok(!refcount, "Device has %u references left.\n", refcount);
10644 IDirect3D9_Release(d3d);
10645 DestroyWindow(window);
10648 static void test_resource_type(void)
10650 IDirect3DDevice9 *device;
10651 IDirect3DSurface9 *surface;
10652 IDirect3DTexture9 *texture;
10653 IDirect3DCubeTexture9 *cube_texture;
10654 IDirect3DVolume9 *volume;
10655 IDirect3DVolumeTexture9 *volume_texture;
10656 D3DSURFACE_DESC surface_desc;
10657 D3DVOLUME_DESC volume_desc;
10658 D3DRESOURCETYPE type;
10659 IDirect3D9 *d3d;
10660 ULONG refcount;
10661 HWND window;
10662 HRESULT hr;
10663 D3DCAPS9 caps;
10665 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10666 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10667 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10668 ok(!!d3d, "Failed to create a D3D object.\n");
10669 if (!(device = create_device(d3d, window, NULL)))
10671 skip("Failed to create a D3D device, skipping tests.\n");
10672 IDirect3D9_Release(d3d);
10673 DestroyWindow(window);
10674 return;
10677 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10678 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10680 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10681 D3DPOOL_SYSTEMMEM, &surface, NULL);
10682 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10683 type = IDirect3DSurface9_GetType(surface);
10684 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10685 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10686 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10687 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10688 surface_desc.Type);
10689 IDirect3DSurface9_Release(surface);
10691 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10692 D3DPOOL_SYSTEMMEM, &texture, NULL);
10693 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10694 type = IDirect3DTexture9_GetType(texture);
10695 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10697 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10698 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10699 /* The following code crashes, for the sake of completeness:
10700 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10701 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10703 * So applications will not depend on getting the "right" resource type - whatever it
10704 * may be - from the "wrong" vtable. */
10705 type = IDirect3DSurface9_GetType(surface);
10706 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10707 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10708 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10709 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10710 surface_desc.Type);
10711 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10712 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10713 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10714 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10715 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10716 surface_desc.Type);
10717 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10718 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10719 IDirect3DSurface9_Release(surface);
10721 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10722 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10723 type = IDirect3DSurface9_GetType(surface);
10724 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10725 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10726 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10727 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10728 surface_desc.Type);
10729 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10730 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10731 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10732 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10733 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10734 surface_desc.Type);
10735 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10736 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10737 IDirect3DSurface9_Release(surface);
10738 IDirect3DTexture9_Release(texture);
10740 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10742 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10743 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10744 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10745 type = IDirect3DCubeTexture9_GetType(cube_texture);
10746 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10748 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10749 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10750 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10751 type = IDirect3DSurface9_GetType(surface);
10752 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10753 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10754 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10755 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10756 surface_desc.Type);
10757 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10758 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10759 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10760 surface_desc.Type);
10761 IDirect3DSurface9_Release(surface);
10762 IDirect3DCubeTexture9_Release(cube_texture);
10764 else
10765 skip("Cube maps not supported.\n");
10767 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10769 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10770 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10771 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10772 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10773 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10775 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10776 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10777 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10778 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10779 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10780 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10781 volume_desc.Type);
10782 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10783 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10784 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10785 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
10786 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10787 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10788 volume_desc.Type);
10789 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10790 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10791 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10792 IDirect3DVolume9_Release(volume);
10794 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
10795 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10796 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10797 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10798 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10799 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10800 volume_desc.Type);
10801 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10802 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10803 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10804 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
10805 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10806 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10807 volume_desc.Type);
10808 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10809 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10810 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10811 IDirect3DVolume9_Release(volume);
10812 IDirect3DVolumeTexture9_Release(volume_texture);
10814 else
10815 skip("Mipmapped volume maps not supported.\n");
10817 refcount = IDirect3DDevice9_Release(device);
10818 ok(!refcount, "Device has %u references left.\n", refcount);
10819 IDirect3D9_Release(d3d);
10820 DestroyWindow(window);
10823 static void test_mipmap_lock(void)
10825 IDirect3DDevice9 *device;
10826 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
10827 IDirect3DTexture9 *texture, *texture_dst;
10828 IDirect3D9 *d3d;
10829 ULONG refcount;
10830 HWND window;
10831 HRESULT hr;
10832 D3DLOCKED_RECT locked_rect;
10834 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10835 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10836 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10837 ok(!!d3d, "Failed to create a D3D object.\n");
10838 if (!(device = create_device(d3d, window, NULL)))
10840 skip("Failed to create a D3D device, skipping tests.\n");
10841 IDirect3D9_Release(d3d);
10842 DestroyWindow(window);
10843 return;
10846 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10847 D3DPOOL_DEFAULT, &texture_dst, NULL);
10848 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10849 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
10850 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10851 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
10852 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10854 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10855 D3DPOOL_SYSTEMMEM, &texture, NULL);
10856 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10857 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10858 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10859 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
10860 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10862 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
10863 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10864 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
10865 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10866 hr = IDirect3DSurface9_UnlockRect(surface);
10867 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10869 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
10870 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
10871 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
10872 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10874 /* Apparently there's no validation on the container. */
10875 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
10876 (IDirect3DBaseTexture9 *)texture_dst);
10877 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
10879 hr = IDirect3DSurface9_UnlockRect(surface2);
10880 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10882 IDirect3DSurface9_Release(surface_dst2);
10883 IDirect3DSurface9_Release(surface_dst);
10884 IDirect3DSurface9_Release(surface2);
10885 IDirect3DSurface9_Release(surface);
10886 IDirect3DTexture9_Release(texture_dst);
10887 IDirect3DTexture9_Release(texture);
10889 refcount = IDirect3DDevice9_Release(device);
10890 ok(!refcount, "Device has %u references left.\n", refcount);
10891 IDirect3D9_Release(d3d);
10892 DestroyWindow(window);
10895 static void test_writeonly_resource(void)
10897 IDirect3D9 *d3d;
10898 IDirect3DDevice9 *device;
10899 IDirect3DVertexBuffer9 *buffer;
10900 ULONG refcount;
10901 HWND window;
10902 HRESULT hr;
10903 void *ptr;
10904 static const struct
10906 struct vec3 pos;
10908 quad[] =
10910 {{-1.0f, -1.0f, 0.0f}},
10911 {{-1.0f, 1.0f, 0.0f}},
10912 {{ 1.0f, -1.0f, 0.0f}},
10913 {{ 1.0f, 1.0f, 0.0f}}
10916 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10917 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10918 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10919 ok(!!d3d, "Failed to create a D3D object.\n");
10920 if (!(device = create_device(d3d, window, NULL)))
10922 skip("Failed to create a D3D device, skipping tests.\n");
10923 IDirect3D9_Release(d3d);
10924 DestroyWindow(window);
10925 return;
10928 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
10929 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
10930 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
10932 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10933 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10934 memcpy(ptr, quad, sizeof(quad));
10935 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10936 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10937 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
10938 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
10939 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10940 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10942 hr = IDirect3DDevice9_BeginScene(device);
10943 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
10944 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
10945 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10946 hr = IDirect3DDevice9_EndScene(device);
10947 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
10949 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
10950 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10951 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10952 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10953 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10955 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
10956 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10957 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10958 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10959 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10961 refcount = IDirect3DVertexBuffer9_Release(buffer);
10962 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
10963 refcount = IDirect3DDevice9_Release(device);
10964 ok(!refcount, "Device has %u references left.\n", refcount);
10965 IDirect3D9_Release(d3d);
10966 DestroyWindow(window);
10969 static void test_lost_device(void)
10971 struct device_desc device_desc;
10972 IDirect3DDevice9 *device;
10973 IDirect3D9 *d3d;
10974 ULONG refcount;
10975 HWND window;
10976 HRESULT hr;
10977 BOOL ret;
10979 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10980 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10981 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10982 ok(!!d3d, "Failed to create a D3D object.\n");
10983 device_desc.device_window = window;
10984 device_desc.width = registry_mode.dmPelsWidth;
10985 device_desc.height = registry_mode.dmPelsHeight;
10986 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10987 if (!(device = create_device(d3d, window, &device_desc)))
10989 skip("Failed to create a D3D device, skipping tests.\n");
10990 goto done;
10993 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10994 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10995 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10996 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10998 ret = SetForegroundWindow(GetDesktopWindow());
10999 ok(ret, "Failed to set foreground window.\n");
11000 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11001 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11002 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11003 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11005 ret = ShowWindow(window, SW_RESTORE);
11006 ok(ret, "Failed to restore window.\n");
11007 ret = SetForegroundWindow(window);
11008 ok(ret, "Failed to set foreground window.\n");
11009 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11010 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
11011 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11012 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11014 hr = reset_device(device, &device_desc);
11015 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11016 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11017 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11018 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11019 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11021 device_desc.flags = 0;
11022 hr = reset_device(device, &device_desc);
11023 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11024 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11025 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11026 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11027 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11029 ret = SetForegroundWindow(GetDesktopWindow());
11030 ok(ret, "Failed to set foreground window.\n");
11031 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11032 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11033 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11034 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11036 ret = ShowWindow(window, SW_RESTORE);
11037 ok(ret, "Failed to restore window.\n");
11038 ret = SetForegroundWindow(window);
11039 ok(ret, "Failed to set foreground window.\n");
11040 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11041 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11042 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11043 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11045 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11046 hr = reset_device(device, &device_desc);
11047 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11048 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11049 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11050 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11051 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11053 ret = SetForegroundWindow(GetDesktopWindow());
11054 ok(ret, "Failed to set foreground window.\n");
11055 hr = reset_device(device, &device_desc);
11056 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11057 ret = ShowWindow(window, SW_RESTORE);
11058 ok(ret, "Failed to restore window.\n");
11059 ret = SetForegroundWindow(window);
11060 ok(ret, "Failed to set foreground window.\n");
11061 hr = reset_device(device, &device_desc);
11062 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11064 refcount = IDirect3DDevice9_Release(device);
11065 ok(!refcount, "Device has %u references left.\n", refcount);
11066 done:
11067 IDirect3D9_Release(d3d);
11068 DestroyWindow(window);
11071 static void test_resource_priority(void)
11073 IDirect3DDevice9 *device;
11074 IDirect3DSurface9 *surface;
11075 IDirect3DTexture9 *texture;
11076 IDirect3DVertexBuffer9 *buffer;
11077 IDirect3D9 *d3d;
11078 ULONG refcount;
11079 HWND window;
11080 HRESULT hr;
11081 static const struct
11083 D3DPOOL pool;
11084 const char *name;
11085 BOOL can_set_priority;
11087 test_data[] =
11089 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
11090 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
11091 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
11092 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
11094 unsigned int i;
11095 DWORD priority;
11097 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11098 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11099 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11100 ok(!!d3d, "Failed to create a D3D object.\n");
11101 if (!(device = create_device(d3d, window, NULL)))
11103 skip("Failed to create a D3D device, skipping tests.\n");
11104 IDirect3D9_Release(d3d);
11105 DestroyWindow(window);
11106 return;
11109 for (i = 0; i < ARRAY_SIZE(test_data); i++)
11111 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
11112 test_data[i].pool, &texture, NULL);
11113 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
11114 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11115 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11117 priority = IDirect3DTexture9_GetPriority(texture);
11118 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11119 priority = IDirect3DTexture9_SetPriority(texture, 1);
11120 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11121 priority = IDirect3DTexture9_GetPriority(texture);
11122 if (test_data[i].can_set_priority)
11124 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11125 priority = IDirect3DTexture9_SetPriority(texture, 2);
11126 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11128 else
11129 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11131 priority = IDirect3DSurface9_GetPriority(surface);
11132 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11133 priority = IDirect3DSurface9_SetPriority(surface, 1);
11134 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11135 priority = IDirect3DSurface9_GetPriority(surface);
11136 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11138 IDirect3DSurface9_Release(surface);
11139 IDirect3DTexture9_Release(texture);
11141 if (test_data[i].pool != D3DPOOL_MANAGED)
11143 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
11144 test_data[i].pool, &surface, NULL);
11145 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
11147 priority = IDirect3DSurface9_GetPriority(surface);
11148 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11149 priority = IDirect3DSurface9_SetPriority(surface, 1);
11150 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11151 priority = IDirect3DSurface9_GetPriority(surface);
11152 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11154 IDirect3DSurface9_Release(surface);
11157 if (test_data[i].pool != D3DPOOL_SCRATCH)
11159 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
11160 test_data[i].pool, &buffer, NULL);
11161 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
11163 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11164 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11165 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
11166 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11167 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11168 if (test_data[i].can_set_priority)
11170 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11171 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
11172 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11174 else
11175 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11177 IDirect3DVertexBuffer9_Release(buffer);
11181 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
11182 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11184 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11185 priority = IDirect3DSurface9_GetPriority(surface);
11186 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11187 priority = IDirect3DSurface9_SetPriority(surface, 1);
11188 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11189 priority = IDirect3DSurface9_GetPriority(surface);
11190 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11192 IDirect3DSurface9_Release(surface);
11194 refcount = IDirect3DDevice9_Release(device);
11195 ok(!refcount, "Device has %u references left.\n", refcount);
11196 IDirect3D9_Release(d3d);
11197 DestroyWindow(window);
11200 static void test_swapchain_parameters(void)
11202 IDirect3DDevice9 *device;
11203 IDirect3D9 *d3d;
11204 HWND window;
11205 HRESULT hr;
11206 unsigned int i;
11207 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
11208 IDirect3DSwapChain9 *swapchain;
11209 static const struct
11211 BOOL windowed;
11212 UINT backbuffer_count;
11213 D3DSWAPEFFECT swap_effect;
11214 HRESULT hr;
11216 tests[] =
11218 /* Swap effect 0 is not allowed. */
11219 {TRUE, 1, 0, D3DERR_INVALIDCALL},
11220 {FALSE, 1, 0, D3DERR_INVALIDCALL},
11222 /* All (non-ex) swap effects are allowed in
11223 * windowed and fullscreen mode. */
11224 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11225 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11226 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11227 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11228 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11230 /* Only one backbuffer in copy mode. */
11231 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
11232 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11233 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11234 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11236 /* Ok with the others, in fullscreen and windowed mode. */
11237 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11238 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11239 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11240 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11242 /* D3D9Ex swap effects. */
11243 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11244 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11245 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11246 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11247 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11248 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11250 /* 3 is the highest allowed backbuffer count. */
11251 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11252 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11253 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11254 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11255 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11258 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11259 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11260 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11261 ok(!!d3d, "Failed to create a D3D object.\n");
11262 if (!(device = create_device(d3d, window, NULL)))
11264 skip("Failed to create a D3D device, skipping tests.\n");
11265 IDirect3D9_Release(d3d);
11266 DestroyWindow(window);
11267 return;
11269 IDirect3DDevice9_Release(device);
11271 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11272 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11273 present_parameters_windowed.hDeviceWindow = window;
11274 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11275 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11276 present_parameters_windowed.Windowed = TRUE;
11277 present_parameters_windowed.BackBufferCount = 1;
11279 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11281 memset(&present_parameters, 0, sizeof(present_parameters));
11282 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11283 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11284 present_parameters.hDeviceWindow = window;
11285 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11287 present_parameters.SwapEffect = tests[i].swap_effect;
11288 present_parameters.Windowed = tests[i].windowed;
11289 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11291 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11292 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11293 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11294 if (SUCCEEDED(hr))
11296 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11298 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11299 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11301 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11302 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11303 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11304 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11305 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11306 bb_count, present_parameters2.BackBufferCount, i);
11307 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11308 tests[i].windowed, present_parameters2.Windowed, i);
11310 IDirect3DSwapChain9_Release(swapchain);
11311 IDirect3DDevice9_Release(device);
11314 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11315 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11316 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11318 memset(&present_parameters, 0, sizeof(present_parameters));
11319 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11320 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11321 present_parameters.hDeviceWindow = window;
11322 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11324 present_parameters.SwapEffect = tests[i].swap_effect;
11325 present_parameters.Windowed = tests[i].windowed;
11326 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11328 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11329 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11331 if (FAILED(hr))
11333 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11334 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11336 IDirect3DDevice9_Release(device);
11339 IDirect3D9_Release(d3d);
11340 DestroyWindow(window);
11343 static void test_check_device_format(void)
11345 IDirect3D9 *d3d;
11346 HRESULT hr;
11348 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11349 ok(!!d3d, "Failed to create a D3D object.\n");
11351 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11352 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11354 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11356 else
11358 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11359 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11360 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11361 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11362 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11363 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11366 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11367 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11368 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11369 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11370 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11371 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11372 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11373 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11374 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11376 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11377 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11378 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11379 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11380 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11381 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11382 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11383 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11384 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11386 IDirect3D9_Release(d3d);
11389 static void test_miptree_layout(void)
11391 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11392 IDirect3DCubeTexture9 *texture_cube;
11393 IDirect3DTexture9 *texture_2d;
11394 IDirect3DDevice9 *device;
11395 D3DLOCKED_RECT map_desc;
11396 BYTE *base = NULL;
11397 IDirect3D9 *d3d;
11398 D3DCAPS9 caps;
11399 UINT refcount;
11400 HWND window;
11401 HRESULT hr;
11403 static const struct
11405 D3DFORMAT format;
11406 const char *name;
11408 formats[] =
11410 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11411 {D3DFMT_A8, "D3DFMT_A8"},
11412 {D3DFMT_L8, "D3DFMT_L8"},
11413 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11414 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11416 static const struct
11418 D3DPOOL pool;
11419 const char *name;
11421 pools[] =
11423 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11424 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11425 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11428 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11429 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11430 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11431 ok(!!d3d, "Failed to create a D3D object.\n");
11432 if (!(device = create_device(d3d, window, NULL)))
11434 skip("Failed to create a D3D device, skipping tests.\n");
11435 goto done;
11438 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11439 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11441 base_dimension = 257;
11442 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11444 skip("Using power of two base dimension.\n");
11445 base_dimension = 256;
11448 for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx)
11450 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11451 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11453 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11454 continue;
11457 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11459 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11460 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11461 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11462 pools[pool_idx].name, formats[format_idx].name, hr);
11464 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11465 for (i = 0, offset = 0; i < level_count; ++i)
11467 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11468 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11469 pools[pool_idx].name, formats[format_idx].name, i, hr);
11471 if (!i)
11472 base = map_desc.pBits;
11473 else
11474 ok(map_desc.pBits == base + offset,
11475 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11476 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11477 offset += (base_dimension >> i) * map_desc.Pitch;
11479 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11480 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11481 pools[pool_idx].name, formats[format_idx].name, i, hr);
11484 IDirect3DTexture9_Release(texture_2d);
11487 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11488 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11490 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11491 continue;
11494 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11496 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11497 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11498 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11499 pools[pool_idx].name, formats[format_idx].name, hr);
11501 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11502 for (i = 0, offset = 0; i < 6; ++i)
11504 for (j = 0; j < level_count; ++j)
11506 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11507 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11508 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11510 if (!i && !j)
11511 base = map_desc.pBits;
11512 else
11513 ok(map_desc.pBits == base + offset,
11514 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11515 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11516 offset += (base_dimension >> j) * map_desc.Pitch;
11518 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11519 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11520 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11522 offset = (offset + 15) & ~15;
11525 IDirect3DCubeTexture9_Release(texture_cube);
11529 refcount = IDirect3DDevice9_Release(device);
11530 ok(!refcount, "Device has %u references left.\n", refcount);
11531 done:
11532 IDirect3D9_Release(d3d);
11533 DestroyWindow(window);
11536 static void test_get_render_target_data(void)
11538 IDirect3DSurface9 *offscreen_surface, *render_target;
11539 IDirect3DDevice9 *device;
11540 IDirect3D9 *d3d;
11541 UINT refcount;
11542 HWND window;
11543 HRESULT hr;
11545 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11546 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11547 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11548 ok(!!d3d, "Failed to create a D3D object.\n");
11549 if (!(device = create_device(d3d, window, NULL)))
11551 skip("Failed to create a D3D device.\n");
11552 IDirect3D9_Release(d3d);
11553 DestroyWindow(window);
11554 return;
11557 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11558 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11559 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11561 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11562 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11563 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11565 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11566 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11568 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11569 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11571 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11572 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11574 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11575 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11577 IDirect3DSurface9_Release(render_target);
11578 IDirect3DSurface9_Release(offscreen_surface);
11579 refcount = IDirect3DDevice9_Release(device);
11580 ok(!refcount, "Device has %u references left.\n", refcount);
11581 IDirect3D9_Release(d3d);
11582 DestroyWindow(window);
11585 static void test_render_target_device_mismatch(void)
11587 IDirect3DDevice9 *device, *device2;
11588 IDirect3DSurface9 *surface, *rt;
11589 IDirect3D9 *d3d;
11590 UINT refcount;
11591 HWND window;
11592 HRESULT hr;
11594 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11595 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11596 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11597 ok(!!d3d, "Failed to create a D3D object.\n");
11598 if (!(device = create_device(d3d, window, NULL)))
11600 skip("Failed to create a D3D device.\n");
11601 IDirect3D9_Release(d3d);
11602 DestroyWindow(window);
11603 return;
11606 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
11607 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11609 device2 = create_device(d3d, window, NULL);
11610 ok(!!device2, "Failed to create a D3D device.\n");
11612 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11613 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11614 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11616 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11617 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11619 IDirect3DSurface9_Release(surface);
11621 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11622 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11624 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11625 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11627 IDirect3DSurface9_Release(surface);
11629 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11630 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11631 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11632 IDirect3DSurface9_Release(surface);
11633 IDirect3DSurface9_Release(rt);
11635 refcount = IDirect3DDevice9_Release(device);
11636 ok(!refcount, "Device has %u references left.\n", refcount);
11637 refcount = IDirect3DDevice9_Release(device2);
11638 ok(!refcount, "Device has %u references left.\n", refcount);
11639 IDirect3D9_Release(d3d);
11640 DestroyWindow(window);
11643 static void test_format_unknown(void)
11645 IDirect3DDevice9 *device;
11646 IDirect3D9 *d3d;
11647 UINT refcount;
11648 HWND window;
11649 void *iface;
11650 HRESULT hr;
11652 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11653 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11654 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11655 ok(!!d3d, "Failed to create a D3D object.\n");
11656 if (!(device = create_device(d3d, window, NULL)))
11658 skip("Failed to create a D3D device.\n");
11659 IDirect3D9_Release(d3d);
11660 DestroyWindow(window);
11661 return;
11664 iface = (void *)0xdeadbeef;
11665 hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64,
11666 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
11667 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11668 ok(!iface, "Got unexpected iface %p.\n", iface);
11670 iface = (void *)0xdeadbeef;
11671 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 64, 64,
11672 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
11673 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11674 ok(!iface, "Got unexpected iface %p.\n", iface);
11676 iface = (void *)0xdeadbeef;
11677 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
11678 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
11679 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11680 ok(!iface, "Got unexpected iface %p.\n", iface);
11682 iface = (void *)0xdeadbeef;
11683 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
11684 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
11685 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11686 ok(!iface, "Got unexpected iface %p.\n", iface);
11688 iface = (void *)0xdeadbeef;
11689 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 1, 0,
11690 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
11691 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11692 ok(!iface, "Got unexpected iface %p.\n", iface);
11694 iface = (void *)0xdeadbeef;
11695 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
11696 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
11697 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11698 ok(!iface, "Got unexpected iface %p.\n", iface);
11700 refcount = IDirect3DDevice9_Release(device);
11701 ok(!refcount, "Device has %u references left.\n", refcount);
11702 IDirect3D9_Release(d3d);
11703 DestroyWindow(window);
11706 static void test_destroyed_window(void)
11708 IDirect3DDevice9 *device;
11709 IDirect3D9 *d3d9;
11710 ULONG refcount;
11711 HWND window;
11712 HRESULT hr;
11714 /* No WS_VISIBLE. */
11715 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11716 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11717 ok(!!window, "Failed to create a window.\n");
11719 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
11720 ok(!!d3d9, "Failed to create a D3D object.\n");
11721 device = create_device(d3d9, window, NULL);
11722 IDirect3D9_Release(d3d9);
11723 DestroyWindow(window);
11724 if (!device)
11726 skip("Failed to create a 3D device, skipping test.\n");
11727 return;
11730 hr = IDirect3DDevice9_BeginScene(device);
11731 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11732 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
11733 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11734 hr = IDirect3DDevice9_EndScene(device);
11735 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11736 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11737 ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
11739 refcount = IDirect3DDevice9_Release(device);
11740 ok(!refcount, "Device has %u references left.\n", refcount);
11743 static void test_lockable_backbuffer(void)
11745 D3DPRESENT_PARAMETERS present_parameters = {0};
11746 struct device_desc device_desc;
11747 IDirect3DSurface9 *surface;
11748 IDirect3DDevice9 *device;
11749 D3DLOCKED_RECT lockrect;
11750 IDirect3D9 *d3d;
11751 ULONG refcount;
11752 HWND window;
11753 HRESULT hr;
11754 HDC dc;
11756 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
11757 0, 0, 640, 480, 0, 0, 0, 0);
11758 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11759 ok(!!d3d, "Failed to create a D3D object.\n");
11761 if (!(device = create_device(d3d, window, NULL)))
11763 skip("Failed to create a D3D device, skipping tests.\n");
11764 IDirect3D9_Release(d3d);
11765 DestroyWindow(window);
11766 return;
11769 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
11770 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
11772 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
11773 todo_wine
11774 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11776 dc = (void *)0xdeadbeef;
11777 hr = IDirect3DSurface9_GetDC(surface, &dc);
11778 ok(dc == (void *)0xdeadbeef, "Unexpected DC returned.\n");
11779 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11781 IDirect3DSurface9_Release(surface);
11783 /* Reset with D3DPRESENTFLAG_LOCKABLE_BACKBUFFER. */
11784 present_parameters.BackBufferWidth = 640;
11785 present_parameters.BackBufferHeight = 480;
11786 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
11787 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
11788 present_parameters.hDeviceWindow = window;
11789 present_parameters.Windowed = TRUE;
11790 present_parameters.EnableAutoDepthStencil = TRUE;
11791 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
11792 present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
11794 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11795 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
11797 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
11798 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
11800 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
11801 todo_wine
11802 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
11803 hr = IDirect3DSurface9_UnlockRect(surface);
11804 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
11806 IDirect3DSurface9_Release(surface);
11807 refcount = IDirect3DDevice9_Release(device);
11808 ok(!refcount, "Device has %u references left.\n", refcount);
11810 device_desc.width = 640;
11811 device_desc.height = 480;
11812 device_desc.device_window = window;
11813 device_desc.flags = CREATE_DEVICE_LOCKABLE_BACKBUFFER;
11815 device = create_device(d3d, window, &device_desc);
11816 ok(!!device, "Failed to create device.\n");
11818 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
11819 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
11821 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
11822 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
11823 hr = IDirect3DSurface9_UnlockRect(surface);
11824 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
11826 IDirect3DSurface9_Release(surface);
11827 refcount = IDirect3DDevice9_Release(device);
11828 ok(!refcount, "Device has %u references left.\n", refcount);
11829 IDirect3D9_Release(d3d);
11830 DestroyWindow(window);
11833 START_TEST(device)
11835 WNDCLASSA wc = {0};
11836 IDirect3D9 *d3d9;
11837 DEVMODEW current_mode;
11839 memset(&current_mode, 0, sizeof(current_mode));
11840 current_mode.dmSize = sizeof(current_mode);
11841 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
11842 registry_mode.dmSize = sizeof(registry_mode);
11843 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
11844 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
11845 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
11847 skip("Current mode does not match registry mode, skipping test.\n");
11848 return;
11851 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
11853 skip("could not create D3D9 object\n");
11854 return;
11856 IDirect3D9_Release(d3d9);
11858 wc.lpfnWndProc = DefWindowProcA;
11859 wc.lpszClassName = "d3d9_test_wc";
11860 RegisterClassA(&wc);
11862 test_get_set_vertex_declaration();
11863 test_get_declaration();
11864 test_fvf_decl_conversion();
11865 test_fvf_decl_management();
11866 test_vertex_declaration_alignment();
11867 test_unused_declaration_type();
11868 test_fpu_setup();
11869 test_multi_device();
11870 test_display_formats();
11871 test_display_modes();
11872 test_swapchain();
11873 test_refcount();
11874 test_mipmap_levels();
11875 test_checkdevicemultisampletype();
11876 test_invalid_multisample();
11877 test_cursor();
11878 test_cursor_pos();
11879 test_reset_fullscreen();
11880 test_reset();
11881 test_scene();
11882 test_limits();
11883 test_depthstenciltest();
11884 test_get_rt();
11885 test_draw_primitive();
11886 test_null_stream();
11887 test_lights();
11888 test_set_stream_source();
11889 test_scissor_size();
11890 test_wndproc();
11891 test_wndproc_windowed();
11892 test_window_style();
11893 test_mode_change();
11894 test_device_window_reset();
11895 test_reset_resources();
11896 test_set_rt_vp_scissor();
11897 test_volume_get_container();
11898 test_volume_resource();
11899 test_vb_lock_flags();
11900 test_vertex_buffer_alignment();
11901 test_query_support();
11902 test_occlusion_query();
11903 test_timestamp_query();
11904 test_get_set_vertex_shader();
11905 test_vertex_shader_constant();
11906 test_get_set_pixel_shader();
11907 test_pixel_shader_constant();
11908 test_unsupported_shaders();
11909 test_texture_stage_states();
11910 test_cube_textures();
11911 test_mipmap_gen();
11912 test_filter();
11913 test_get_set_texture();
11914 test_lod();
11915 test_surface_get_container();
11916 test_surface_alignment();
11917 test_lockrect_offset();
11918 test_lockrect_invalid();
11919 test_private_data();
11920 test_getdc();
11921 test_surface_dimensions();
11922 test_surface_format_null();
11923 test_surface_double_unlock();
11924 test_surface_blocks();
11925 test_set_palette();
11926 test_swvp_buffer();
11927 test_managed_buffer();
11928 test_npot_textures();
11929 test_vidmem_accounting();
11930 test_volume_locking();
11931 test_update_volumetexture();
11932 test_create_rt_ds_fail();
11933 test_volume_blocks();
11934 test_lockbox_invalid();
11935 test_shared_handle();
11936 test_pixel_format();
11937 test_begin_end_state_block();
11938 test_shader_constant_apply();
11939 test_vdecl_apply();
11940 test_resource_type();
11941 test_mipmap_lock();
11942 test_writeonly_resource();
11943 test_lost_device();
11944 test_resource_priority();
11945 test_swapchain_parameters();
11946 test_check_device_format();
11947 test_miptree_layout();
11948 test_get_render_target_data();
11949 test_render_target_device_mismatch();
11950 test_format_unknown();
11951 test_destroyed_window();
11952 test_lockable_backbuffer();
11954 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));