d3d9: Check the device status in present calls.
[wine.git] / dlls / d3d9 / tests / device.c
blobb11771ff2352125c5cae5dd57dc164eac6caee07
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 COBJMACROS
26 #include <d3d9.h>
27 #include "wine/test.h"
29 struct vec3
31 float x, y, z;
34 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
35 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
37 static INT screen_width;
38 static INT screen_height;
40 static const DWORD simple_vs[] =
42 0xfffe0101, /* vs_1_1 */
43 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
44 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
45 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
46 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
47 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
48 0x0000ffff, /* end */
51 static const DWORD simple_ps[] =
53 0xffff0101, /* ps_1_1 */
54 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
55 0x00000042, 0xb00f0000, /* tex t0 */
56 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
57 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
58 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
59 0x0000ffff, /* end */
62 static int get_refcount(IUnknown *object)
64 IUnknown_AddRef( object );
65 return IUnknown_Release( object );
68 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
70 unsigned int element_count, i;
71 D3DVERTEXELEMENT9 *elements;
72 BOOL equal = TRUE;
73 HRESULT hr;
75 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
76 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
77 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
78 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
79 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
81 for (i = 0; i < element_count; ++i)
83 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
85 equal = FALSE;
86 break;
90 if (!equal)
92 for (i = 0; i < element_count; ++i)
94 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
95 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
96 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
100 HeapFree(GetProcessHeap(), 0, elements);
101 return equal;
104 /* try to make sure pending X events have been processed before continuing */
105 static void flush_events(void)
107 MSG msg;
108 int diff = 200;
109 int min_timeout = 100;
110 DWORD time = GetTickCount() + diff;
112 while (diff > 0)
114 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
115 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
116 diff = time - GetTickCount();
120 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND device_window, HWND focus_window, BOOL windowed)
122 D3DPRESENT_PARAMETERS present_parameters = {0};
123 IDirect3DDevice9 *device;
125 present_parameters.Windowed = windowed;
126 present_parameters.hDeviceWindow = device_window;
127 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
128 present_parameters.BackBufferWidth = screen_width;
129 present_parameters.BackBufferHeight = screen_height;
130 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
131 present_parameters.EnableAutoDepthStencil = TRUE;
132 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
134 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
135 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
137 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
138 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
139 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
141 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
142 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
144 return NULL;
147 static HRESULT reset_device(IDirect3DDevice9 *device, HWND device_window, BOOL windowed)
149 D3DPRESENT_PARAMETERS present_parameters = {0};
151 present_parameters.Windowed = windowed;
152 present_parameters.hDeviceWindow = device_window;
153 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
154 present_parameters.BackBufferWidth = screen_width;
155 present_parameters.BackBufferHeight = screen_height;
156 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
157 present_parameters.EnableAutoDepthStencil = TRUE;
158 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
160 return IDirect3DDevice9_Reset(device, &present_parameters);
163 #define CHECK_CALL(r,c,d,rc) \
164 if (SUCCEEDED(r)) {\
165 int tmp1 = get_refcount( (IUnknown *)d ); \
166 int rc_new = rc; \
167 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
168 } else {\
169 trace("%s failed: %08x\n", c, r); \
172 #define CHECK_RELEASE(obj,d,rc) \
173 if (obj) { \
174 int tmp1, rc_new = rc; \
175 IUnknown_Release( (IUnknown*)obj ); \
176 tmp1 = get_refcount( (IUnknown *)d ); \
177 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
180 #define CHECK_REFCOUNT(obj,rc) \
182 int rc_new = rc; \
183 int count = get_refcount( (IUnknown *)obj ); \
184 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
187 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
189 int rc_new = rc; \
190 int count = IUnknown_Release( (IUnknown *)obj ); \
191 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
194 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
196 int rc_new = rc; \
197 int count = IUnknown_AddRef( (IUnknown *)obj ); \
198 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
201 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
203 void *container_ptr = (void *)0x1337c0d3; \
204 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
205 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
206 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
207 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
210 static void test_get_set_vertex_declaration(void)
212 IDirect3DVertexDeclaration9 *declaration, *tmp;
213 ULONG refcount, expected_refcount;
214 IDirect3DDevice9 *device;
215 IDirect3D9 *d3d;
216 HWND window;
217 HRESULT hr;
219 static const D3DVERTEXELEMENT9 simple_decl[] =
221 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
222 D3DDECL_END()
225 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
226 0, 0, 640, 480, NULL, NULL, NULL, NULL);
227 d3d = Direct3DCreate9(D3D_SDK_VERSION);
228 ok(!!d3d, "Failed to create a D3D object.\n");
229 if (!(device = create_device(d3d, window, window, TRUE)))
231 skip("Failed to create a D3D device, skipping tests.\n");
232 goto done;
235 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
236 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
238 /* SetVertexDeclaration() should not touch the declaration's refcount. */
239 expected_refcount = get_refcount((IUnknown *)declaration);
240 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
241 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
242 refcount = get_refcount((IUnknown *)declaration);
243 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
245 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
246 tmp = NULL;
247 expected_refcount = refcount + 1;
248 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
249 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
250 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
251 refcount = get_refcount((IUnknown *)declaration);
252 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
253 IDirect3DVertexDeclaration9_Release(tmp);
255 IDirect3DVertexDeclaration9_Release(declaration);
256 refcount = IDirect3DDevice9_Release(device);
257 ok(!refcount, "Device has %u references left.\n", refcount);
258 done:
259 IDirect3D9_Release(d3d);
260 DestroyWindow(window);
263 static void test_get_declaration(void)
265 unsigned int element_count, expected_element_count;
266 IDirect3DVertexDeclaration9 *declaration;
267 D3DVERTEXELEMENT9 *elements;
268 IDirect3DDevice9 *device;
269 IDirect3D9 *d3d;
270 ULONG refcount;
271 HWND window;
272 HRESULT hr;
274 static const D3DVERTEXELEMENT9 simple_decl[] =
276 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
277 D3DDECL_END()
280 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
281 0, 0, 640, 480, NULL, NULL, NULL, NULL);
282 d3d = Direct3DCreate9(D3D_SDK_VERSION);
283 ok(!!d3d, "Failed to create a D3D object.\n");
284 if (!(device = create_device(d3d, window, window, TRUE)))
286 skip("Failed to create a D3D device, skipping tests.\n");
287 goto done;
290 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
291 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
293 /* First test only getting the number of elements. */
294 element_count = 0x1337c0de;
295 expected_element_count = sizeof(simple_decl) / sizeof(*simple_decl);
296 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
297 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
298 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
299 element_count, expected_element_count);
301 element_count = 0;
302 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
303 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
304 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
305 element_count, expected_element_count);
307 /* Also test the returned data. */
308 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
310 element_count = 0x1337c0de;
311 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
312 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
313 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
314 element_count, expected_element_count);
315 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
316 "Original and returned vertexdeclarations are not the same.\n");
318 memset(elements, 0, sizeof(simple_decl));
320 element_count = 0;
321 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
322 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
323 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
324 element_count, expected_element_count);
325 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
326 "Original and returned vertexdeclarations are not the same.\n");
328 HeapFree(GetProcessHeap(), 0, elements);
329 IDirect3DVertexDeclaration9_Release(declaration);
330 refcount = IDirect3DDevice9_Release(device);
331 ok(!refcount, "Device has %u references left.\n", refcount);
332 done:
333 IDirect3D9_Release(d3d);
334 DestroyWindow(window);
337 static void test_fvf_decl_conversion(void)
339 IDirect3DVertexDeclaration9 *default_decl;
340 IDirect3DVertexDeclaration9 *declaration;
341 IDirect3DDevice9 *device;
342 IDirect3D9 *d3d;
343 ULONG refcount;
344 unsigned int i;
345 HWND window;
346 HRESULT hr;
348 static const D3DVERTEXELEMENT9 default_elements[] =
350 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
351 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
352 D3DDECL_END()
354 /* Test conversions from vertex declaration to an FVF. For some reason
355 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
356 * forced to 0 - maybe this is configuration specific. */
357 static const struct
359 D3DVERTEXELEMENT9 elements[7];
360 DWORD fvf;
361 BOOL todo;
363 decl_to_fvf_tests[] =
365 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
366 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
367 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
368 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
369 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
370 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
371 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
372 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
373 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
374 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
375 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
376 /* No FVF mapping available. */
377 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
378 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
379 /* Try empty declaration. */
380 {{ D3DDECL_END()}, 0, FALSE},
381 /* Make sure textures of different sizes work. */
382 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
383 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
384 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
385 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
386 /* Make sure the TEXCOORD index works correctly - try several textures. */
389 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
390 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
391 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
392 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
393 D3DDECL_END(),
394 }, 0, FALSE,
396 /* Now try a combination test. */
399 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
400 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
401 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
402 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
403 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
404 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
405 D3DDECL_END(),
406 }, 0, FALSE,
409 /* Test conversions from FVF to a vertex declaration. These seem to always
410 * occur internally. A new declaration object is created if necessary. */
411 static const struct
413 DWORD fvf;
414 D3DVERTEXELEMENT9 elements[7];
416 fvf_to_decl_tests[] =
418 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
419 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
420 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
422 D3DFVF_XYZB5,
424 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
425 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
426 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
427 D3DDECL_END(),
431 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
433 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
434 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
435 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
436 D3DDECL_END(),
440 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
442 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
443 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
444 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
445 D3DDECL_END(),
449 D3DFVF_XYZB1,
451 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
452 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
453 D3DDECL_END(),
457 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
459 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
460 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
461 D3DDECL_END(),
465 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
467 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
468 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
469 D3DDECL_END(),
473 D3DFVF_XYZB2,
475 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
476 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
477 D3DDECL_END(),
481 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
483 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
484 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
485 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
486 D3DDECL_END(),
490 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
492 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
493 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
494 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
495 D3DDECL_END(),
499 D3DFVF_XYZB3,
501 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
502 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
503 D3DDECL_END(),
507 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
509 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
510 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
511 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
512 D3DDECL_END(),
516 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
518 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
519 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
520 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
521 D3DDECL_END(),
525 D3DFVF_XYZB4,
527 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
528 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
529 D3DDECL_END(),
533 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
535 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
536 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
537 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
538 D3DDECL_END(),
542 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
544 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
545 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
546 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
547 D3DDECL_END(),
550 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
551 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
552 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
553 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
554 /* Make sure textures of different sizes work. */
556 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
557 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
560 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
561 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
564 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
565 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
568 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
569 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
571 /* Make sure the TEXCOORD index works correctly - try several textures. */
573 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
574 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
576 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
577 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
578 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
579 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
580 D3DDECL_END(),
583 /* Now try a combination test. */
585 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
586 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
588 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
589 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
590 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
591 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
592 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
593 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
594 D3DDECL_END(),
599 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
600 0, 0, 640, 480, NULL, NULL, NULL, NULL);
601 d3d = Direct3DCreate9(D3D_SDK_VERSION);
602 ok(!!d3d, "Failed to create a D3D object.\n");
603 if (!(device = create_device(d3d, window, window, TRUE)))
605 skip("Failed to create a D3D device, skipping tests.\n");
606 goto done;
609 for (i = 0; i < sizeof(decl_to_fvf_tests) / sizeof(*decl_to_fvf_tests); ++i)
611 DWORD fvf = 0xdeadbeef;
612 HRESULT hr;
614 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
615 * back to 0. */
616 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
617 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
619 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
620 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
621 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
622 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
624 /* Check the FVF. */
625 hr = IDirect3DDevice9_GetFVF(device, &fvf);
626 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
628 if (decl_to_fvf_tests[i].todo)
629 todo_wine ok(fvf == decl_to_fvf_tests[i].fvf,
630 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
631 i, fvf, decl_to_fvf_tests[i].fvf);
632 else
633 ok(fvf == decl_to_fvf_tests[i].fvf,
634 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
635 i, fvf, decl_to_fvf_tests[i].fvf);
637 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
638 IDirect3DVertexDeclaration9_Release(declaration);
641 /* Create a default declaration and FVF that does not match any of the
642 * tests. */
643 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
644 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
646 for (i = 0; i < sizeof(fvf_to_decl_tests) / sizeof(*fvf_to_decl_tests); ++i)
648 /* Set a default declaration to make sure it is changed. */
649 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
650 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
652 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
653 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
655 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
656 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
657 ok(!!declaration && declaration != default_decl,
658 "Test %u: Got unexpected declaration %p.\n", i, declaration);
659 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
660 "Test %u: Declaration does not match.\n", i);
661 IDirect3DVertexDeclaration9_Release(declaration);
664 /* Setting the FVF to 0 should result in no change to the default decl. */
665 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
666 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
667 hr = IDirect3DDevice9_SetFVF(device, 0);
668 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
669 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
670 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
671 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
672 IDirect3DVertexDeclaration9_Release(declaration);
674 IDirect3DVertexDeclaration9_Release(default_decl);
675 refcount = IDirect3DDevice9_Release(device);
676 ok(!refcount, "Device has %u references left.\n", refcount);
677 done:
678 IDirect3D9_Release(d3d);
679 DestroyWindow(window);
682 /* Check whether a declaration converted from FVF is shared.
683 * Check whether refcounts behave as expected. */
684 static void test_fvf_decl_management(void)
686 IDirect3DVertexDeclaration9 *declaration1;
687 IDirect3DVertexDeclaration9 *declaration2;
688 IDirect3DVertexDeclaration9 *declaration3;
689 IDirect3DVertexDeclaration9 *declaration4;
690 IDirect3DDevice9 *device;
691 IDirect3D9 *d3d;
692 ULONG refcount;
693 HWND window;
694 HRESULT hr;
696 static const D3DVERTEXELEMENT9 test_elements1[] =
697 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
698 static const D3DVERTEXELEMENT9 test_elements2[] =
699 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
701 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
702 0, 0, 640, 480, NULL, NULL, NULL, NULL);
703 d3d = Direct3DCreate9(D3D_SDK_VERSION);
704 ok(!!d3d, "Failed to create a D3D object.\n");
705 if (!(device = create_device(d3d, window, window, TRUE)))
707 skip("Failed to create a D3D device, skipping tests.\n");
708 goto done;
711 /* Clear down any current vertex declaration. */
712 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
713 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
714 /* Conversion. */
715 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
716 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
717 /* Get converted decl (#1). */
718 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
719 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
720 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
721 /* Get converted decl again (#2). */
722 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
723 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
724 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
726 /* Conversion. */
727 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
728 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
729 /* Get converted decl (#3). */
730 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
731 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
732 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
733 /* The contents should correspond to the second conversion. */
734 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
735 /* Re-Check if the first decl was overwritten by the new Get(). */
736 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
738 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
739 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
740 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
741 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
742 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
744 refcount = get_refcount((IUnknown*)declaration1);
745 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
746 refcount = get_refcount((IUnknown*)declaration2);
747 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
748 refcount = get_refcount((IUnknown*)declaration3);
749 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
750 refcount = get_refcount((IUnknown*)declaration4);
751 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
753 IDirect3DVertexDeclaration9_Release(declaration4);
754 IDirect3DVertexDeclaration9_Release(declaration3);
755 IDirect3DVertexDeclaration9_Release(declaration2);
756 IDirect3DVertexDeclaration9_Release(declaration1);
758 refcount = IDirect3DDevice9_Release(device);
759 ok(!refcount, "Device has %u references left.\n", refcount);
760 done:
761 IDirect3D9_Release(d3d);
762 DestroyWindow(window);
765 static void test_vertex_declaration_alignment(void)
767 IDirect3DVertexDeclaration9 *declaration;
768 IDirect3DDevice9 *device;
769 IDirect3D9 *d3d;
770 unsigned int i;
771 ULONG refcount;
772 HWND window;
773 HRESULT hr;
775 static const struct
777 D3DVERTEXELEMENT9 elements[3];
778 HRESULT hr;
780 test_data[] =
784 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
785 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
786 D3DDECL_END(),
787 }, D3D_OK,
791 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
792 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
793 D3DDECL_END(),
794 }, E_FAIL,
798 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
799 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
800 D3DDECL_END(),
801 }, E_FAIL,
805 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
806 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
807 D3DDECL_END(),
808 }, E_FAIL,
812 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
813 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
814 D3DDECL_END(),
815 }, D3D_OK,
819 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
820 0, 0, 640, 480, NULL, NULL, NULL, NULL);
821 d3d = Direct3DCreate9(D3D_SDK_VERSION);
822 ok(!!d3d, "Failed to create a D3D object.\n");
823 if (!(device = create_device(d3d, window, window, TRUE)))
825 skip("Failed to create a D3D device, skipping tests.\n");
826 goto done;
829 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
831 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
832 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
833 if (SUCCEEDED(hr))
834 IDirect3DVertexDeclaration9_Release(declaration);
837 refcount = IDirect3DDevice9_Release(device);
838 ok(!refcount, "Device has %u references left.\n", refcount);
839 done:
840 IDirect3D9_Release(d3d);
841 DestroyWindow(window);
844 static void test_unused_declaration_type(void)
846 IDirect3DVertexDeclaration9 *declaration;
847 IDirect3DDevice9 *device;
848 IDirect3D9 *d3d;
849 unsigned int i;
850 ULONG refcount;
851 HWND window;
852 HRESULT hr;
854 static const D3DVERTEXELEMENT9 test_elements[][3] =
857 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
858 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
859 D3DDECL_END(),
862 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
863 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
864 D3DDECL_END(),
867 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
868 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
869 D3DDECL_END(),
872 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
873 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
874 D3DDECL_END(),
877 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
878 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
879 D3DDECL_END(),
882 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
883 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
884 D3DDECL_END(),
887 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
888 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
889 D3DDECL_END(),
893 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
894 0, 0, 640, 480, NULL, NULL, NULL, NULL);
895 d3d = Direct3DCreate9(D3D_SDK_VERSION);
896 ok(!!d3d, "Failed to create a D3D object.\n");
897 if (!(device = create_device(d3d, window, window, TRUE)))
899 skip("Failed to create a D3D device, skipping tests.\n");
900 goto done;
903 for (i = 0; i < sizeof(test_elements) / sizeof(*test_elements); ++i)
905 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
906 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
909 refcount = IDirect3DDevice9_Release(device);
910 ok(!refcount, "Device has %u references left.\n", refcount);
911 done:
912 IDirect3D9_Release(d3d);
913 DestroyWindow(window);
916 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
918 IDirect3DBaseTexture9* texture = NULL;
919 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
920 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
922 if (SUCCEEDED(hr)) {
923 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
924 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
925 } else
926 trace("CreateTexture failed: %08x\n", hr);
928 if (texture) IDirect3DBaseTexture9_Release( texture );
931 static void test_mipmap_levels(void)
933 IDirect3DDevice9 *device;
934 IDirect3D9 *d3d;
935 ULONG refcount;
936 HWND window;
938 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
939 0, 0, 640, 480, NULL, NULL, NULL, NULL);
940 ok(!!window, "Failed to create a window.\n");
941 d3d = Direct3DCreate9(D3D_SDK_VERSION);
942 ok(!!d3d, "Failed to create a D3D object.\n");
943 if (!(device = create_device(d3d, window, window, TRUE)))
945 skip("Failed to create a 3D device, skipping test.\n");
946 goto cleanup;
949 check_mipmap_levels(device, 32, 32, 6);
950 check_mipmap_levels(device, 256, 1, 9);
951 check_mipmap_levels(device, 1, 256, 9);
952 check_mipmap_levels(device, 1, 1, 1);
954 refcount = IDirect3DDevice9_Release(device);
955 ok(!refcount, "Device has %u references left.\n", refcount);
956 cleanup:
957 IDirect3D9_Release(d3d);
958 DestroyWindow(window);
961 static void test_checkdevicemultisampletype(void)
963 IDirect3DDevice9 *device;
964 DWORD quality_levels;
965 IDirect3D9 *d3d;
966 ULONG refcount;
967 HWND window;
968 HRESULT hr;
970 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
971 0, 0, 640, 480, NULL, NULL, NULL, NULL);
972 ok(!!window, "Failed to create a window.\n");
973 d3d = Direct3DCreate9(D3D_SDK_VERSION);
974 ok(!!d3d, "Failed to create a D3D object.\n");
975 if (!(device = create_device(d3d, window, window, TRUE)))
977 skip("Failed to create a 3D device, skipping test.\n");
978 goto cleanup;
981 quality_levels = 0;
982 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
983 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
984 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
985 if (hr == D3DERR_NOTAVAILABLE)
987 skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
988 goto cleanup;
990 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
992 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
993 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
994 ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
995 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
997 cleanup:
998 if (device)
1000 refcount = IDirect3DDevice9_Release(device);
1001 ok(!refcount, "Device has %u references left.\n", refcount);
1003 IDirect3D9_Release(d3d);
1004 DestroyWindow(window);
1007 static void test_swapchain(void)
1009 IDirect3DSwapChain9 *swapchain0;
1010 IDirect3DSwapChain9 *swapchain1;
1011 IDirect3DSwapChain9 *swapchain2;
1012 IDirect3DSwapChain9 *swapchain3;
1013 IDirect3DSwapChain9 *swapchainX;
1014 IDirect3DSurface9 *backbuffer;
1015 D3DPRESENT_PARAMETERS d3dpp;
1016 IDirect3DDevice9 *device;
1017 IDirect3D9 *d3d;
1018 ULONG refcount;
1019 HWND window;
1020 HRESULT hr;
1022 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1023 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1024 ok(!!window, "Failed to create a window.\n");
1025 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1026 ok(!!d3d, "Failed to create a D3D object.\n");
1027 if (!(device = create_device(d3d, window, window, TRUE)))
1029 skip("Failed to create a 3D device, skipping test.\n");
1030 goto cleanup;
1033 /* Get the implicit swapchain */
1034 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1035 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1036 /* Check if the back buffer count was modified */
1037 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1038 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1039 IDirect3DSwapChain9_Release(swapchain0);
1041 /* Check if there is a back buffer */
1042 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1043 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1044 ok(backbuffer != NULL, "The back buffer is NULL\n");
1045 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1047 /* Try to get a nonexistent swapchain */
1048 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1049 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1050 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1051 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1053 /* Create a bunch of swapchains */
1054 d3dpp.BackBufferCount = 0;
1055 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1056 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1057 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1059 d3dpp.BackBufferCount = 1;
1060 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1061 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1063 d3dpp.BackBufferCount = 2;
1064 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1065 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1066 if(SUCCEEDED(hr)) {
1067 /* Swapchain 3, created with backbuffercount 2 */
1068 backbuffer = (void *) 0xdeadbeef;
1069 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1070 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1071 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1072 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1074 backbuffer = (void *) 0xdeadbeef;
1075 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1076 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1077 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1078 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1080 backbuffer = (void *) 0xdeadbeef;
1081 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1082 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1083 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1084 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1086 backbuffer = (void *) 0xdeadbeef;
1087 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1088 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1089 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1090 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1093 /* Check the back buffers of the swapchains */
1094 /* Swapchain 1, created with backbuffercount 0 */
1095 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1096 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1097 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1098 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1100 backbuffer = (void *) 0xdeadbeef;
1101 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1102 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1103 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1104 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1106 /* Swapchain 2 - created with backbuffercount 1 */
1107 backbuffer = (void *) 0xdeadbeef;
1108 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1109 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1110 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1111 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1113 backbuffer = (void *) 0xdeadbeef;
1114 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1115 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1116 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1117 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1119 backbuffer = (void *) 0xdeadbeef;
1120 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1121 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1122 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1123 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1125 /* Try getSwapChain on a manually created swapchain
1126 * it should fail, apparently GetSwapChain only returns implicit swapchains
1128 swapchainX = (void *) 0xdeadbeef;
1129 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1130 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1131 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1132 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1134 IDirect3DSwapChain9_Release(swapchain3);
1135 IDirect3DSwapChain9_Release(swapchain2);
1136 IDirect3DSwapChain9_Release(swapchain1);
1137 refcount = IDirect3DDevice9_Release(device);
1138 ok(!refcount, "Device has %u references left.\n", refcount);
1139 cleanup:
1140 IDirect3D9_Release(d3d);
1141 DestroyWindow(window);
1144 static void test_refcount(void)
1146 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1147 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1148 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1149 IDirect3DVertexShader9 *pVertexShader = NULL;
1150 IDirect3DPixelShader9 *pPixelShader = NULL;
1151 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1152 IDirect3DTexture9 *pTexture = NULL;
1153 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1154 IDirect3DVolume9 *pVolumeLevel = NULL;
1155 IDirect3DSurface9 *pStencilSurface = NULL;
1156 IDirect3DSurface9 *pOffscreenSurface = NULL;
1157 IDirect3DSurface9 *pRenderTarget = NULL;
1158 IDirect3DSurface9 *pRenderTarget2 = NULL;
1159 IDirect3DSurface9 *pRenderTarget3 = NULL;
1160 IDirect3DSurface9 *pTextureLevel = NULL;
1161 IDirect3DSurface9 *pBackBuffer = NULL;
1162 IDirect3DStateBlock9 *pStateBlock = NULL;
1163 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1164 IDirect3DSwapChain9 *pSwapChain = NULL;
1165 IDirect3DQuery9 *pQuery = NULL;
1166 D3DPRESENT_PARAMETERS d3dpp;
1167 IDirect3DDevice9 *device;
1168 ULONG refcount = 0, tmp;
1169 IDirect3D9 *d3d, *d3d2;
1170 HWND window;
1171 HRESULT hr;
1173 D3DVERTEXELEMENT9 decl[] =
1175 D3DDECL_END()
1178 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1179 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1180 ok(!!window, "Failed to create a window.\n");
1181 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1182 ok(!!d3d, "Failed to create a D3D object.\n");
1184 CHECK_REFCOUNT(d3d, 1);
1186 if (!(device = create_device(d3d, window, window, TRUE)))
1188 skip("Failed to create a 3D device, skipping test.\n");
1189 goto cleanup;
1192 refcount = get_refcount((IUnknown *)device);
1193 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1195 CHECK_REFCOUNT(d3d, 2);
1197 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1198 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1200 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1201 CHECK_REFCOUNT(d3d, 3);
1202 CHECK_RELEASE_REFCOUNT(d3d, 2);
1205 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1206 * - the container is the device OR swapchain
1207 * - they hold a reference to the device
1208 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1209 * - they are not freed if refcount reaches 0.
1210 * - the refcount is not forwarded to the container.
1212 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1213 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1214 if (pSwapChain)
1216 CHECK_REFCOUNT( pSwapChain, 1);
1218 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1219 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1220 CHECK_REFCOUNT( pSwapChain, 1);
1221 if(pRenderTarget)
1223 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1224 CHECK_REFCOUNT( pRenderTarget, 1);
1226 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1227 CHECK_REFCOUNT(device, refcount);
1228 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1229 CHECK_REFCOUNT(device, refcount);
1231 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1232 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1233 CHECK_REFCOUNT( pRenderTarget, 2);
1234 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
1235 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
1236 CHECK_REFCOUNT(device, --refcount);
1238 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1239 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1240 CHECK_REFCOUNT(device, ++refcount);
1241 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1242 CHECK_REFCOUNT(device, --refcount);
1245 /* Render target and back buffer are identical. */
1246 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1247 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1248 if(pBackBuffer)
1250 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1251 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1252 pRenderTarget, pBackBuffer);
1253 pBackBuffer = NULL;
1255 CHECK_REFCOUNT(device, --refcount);
1257 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1258 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1259 CHECK_REFCOUNT( pSwapChain, 1);
1260 if(pStencilSurface)
1262 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1263 CHECK_REFCOUNT( pStencilSurface, 1);
1265 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1266 CHECK_REFCOUNT(device, refcount);
1267 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1268 CHECK_REFCOUNT(device, refcount);
1270 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
1271 CHECK_REFCOUNT(device, --refcount);
1273 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1274 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1275 CHECK_REFCOUNT(device, ++refcount);
1276 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1277 CHECK_REFCOUNT(device, --refcount);
1278 pStencilSurface = NULL;
1281 CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
1282 CHECK_REFCOUNT(device, --refcount);
1284 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1285 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1286 CHECK_REFCOUNT(device, ++refcount);
1287 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1288 CHECK_REFCOUNT(device, --refcount);
1289 pSwapChain = NULL;
1292 /* Buffers */
1293 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1294 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1295 if(pIndexBuffer)
1297 tmp = get_refcount( (IUnknown *)pIndexBuffer );
1299 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1300 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1301 hr = IDirect3DDevice9_SetIndices(device, NULL);
1302 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1305 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1306 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1307 if(pVertexBuffer)
1309 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1310 UINT offset = ~0;
1311 UINT stride = ~0;
1313 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1315 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1316 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1317 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1318 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1320 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1321 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1322 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1323 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1324 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1326 /* Shaders */
1327 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1328 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1329 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1330 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1331 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1332 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1333 /* Textures */
1334 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1335 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1336 if (pTexture)
1338 tmp = get_refcount( (IUnknown *)pTexture );
1340 /* SetTexture should not increase refcounts */
1341 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1342 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1343 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1344 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1346 /* This should not increment device refcount */
1347 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1348 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1349 /* But should increment texture's refcount */
1350 CHECK_REFCOUNT( pTexture, tmp+1 );
1351 /* Because the texture and surface refcount are identical */
1352 if (pTextureLevel)
1354 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1355 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1356 CHECK_REFCOUNT ( pTexture , tmp+2 );
1357 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1358 CHECK_REFCOUNT ( pTexture , tmp+1 );
1359 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1360 CHECK_REFCOUNT ( pTextureLevel, tmp );
1363 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1364 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1365 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1366 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1367 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1368 if (pVolumeTexture)
1370 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1372 /* This should not increment device refcount */
1373 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1374 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1375 /* But should increment volume texture's refcount */
1376 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1377 /* Because the volume texture and volume refcount are identical */
1378 if (pVolumeLevel)
1380 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1381 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1382 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1383 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1384 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1385 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1386 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1389 /* Surfaces */
1390 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1391 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1392 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1393 CHECK_REFCOUNT( pStencilSurface, 1 );
1394 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1395 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1396 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1397 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1398 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1399 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1400 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1401 CHECK_REFCOUNT( pRenderTarget3, 1 );
1402 /* Misc */
1403 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1404 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1406 memset(&d3dpp, 0, sizeof(d3dpp));
1407 d3dpp.Windowed = TRUE;
1408 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1409 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1410 d3dpp.EnableAutoDepthStencil = TRUE;
1411 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1412 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1413 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1414 if(pSwapChain)
1416 /* check implicit back buffer */
1417 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1418 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1419 CHECK_REFCOUNT( pSwapChain, 1);
1420 if(pBackBuffer)
1422 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1423 CHECK_REFCOUNT( pBackBuffer, 1);
1424 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
1425 CHECK_REFCOUNT(device, --refcount);
1427 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1428 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1429 CHECK_REFCOUNT(device, ++refcount);
1430 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1431 CHECK_REFCOUNT(device, --refcount);
1432 pBackBuffer = NULL;
1434 CHECK_REFCOUNT( pSwapChain, 1);
1436 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1437 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1439 hr = IDirect3DDevice9_BeginStateBlock(device);
1440 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1441 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1442 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1444 /* The implicit render target is not freed if refcount reaches 0.
1445 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1446 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1447 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1448 if(pRenderTarget2)
1450 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1451 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1452 pRenderTarget, pRenderTarget2);
1453 CHECK_REFCOUNT(device, --refcount);
1454 pRenderTarget2 = NULL;
1456 pRenderTarget = NULL;
1458 cleanup:
1459 CHECK_RELEASE(device, device, --refcount);
1461 /* Buffers */
1462 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1463 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1464 /* Shaders */
1465 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1466 CHECK_RELEASE(pVertexShader, device, --refcount);
1467 CHECK_RELEASE(pPixelShader, device, --refcount);
1468 /* Textures */
1469 CHECK_RELEASE(pTextureLevel, device, --refcount);
1470 CHECK_RELEASE(pCubeTexture, device, --refcount);
1471 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1472 /* Surfaces */
1473 CHECK_RELEASE(pStencilSurface, device, --refcount);
1474 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1475 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1476 /* Misc */
1477 CHECK_RELEASE(pStateBlock, device, --refcount);
1478 CHECK_RELEASE(pSwapChain, device, --refcount);
1479 CHECK_RELEASE(pQuery, device, --refcount);
1480 /* This will destroy device - cannot check the refcount here */
1481 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1482 CHECK_RELEASE_REFCOUNT(d3d, 0);
1483 DestroyWindow(window);
1486 static void test_cursor(void)
1488 IDirect3DSurface9 *cursor = NULL;
1489 IDirect3DDevice9 *device;
1490 CURSORINFO info;
1491 IDirect3D9 *d3d;
1492 ULONG refcount;
1493 HCURSOR cur;
1494 HWND window;
1495 HRESULT hr;
1497 memset(&info, 0, sizeof(info));
1498 info.cbSize = sizeof(info);
1499 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1500 cur = info.hCursor;
1502 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1503 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1504 ok(!!window, "Failed to create a window.\n");
1505 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1506 ok(!!d3d, "Failed to create a D3D object.\n");
1507 if (!(device = create_device(d3d, window, window, TRUE)))
1509 skip("Failed to create a 3D device, skipping test.\n");
1510 goto cleanup;
1513 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1514 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1515 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1517 /* Initially hidden */
1518 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1519 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1521 /* Not enabled without a surface*/
1522 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1523 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1525 /* Fails */
1526 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1527 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1529 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1530 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1532 IDirect3DSurface9_Release(cursor);
1534 memset(&info, 0, sizeof(info));
1535 info.cbSize = sizeof(info);
1536 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1537 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
1538 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1540 /* Still hidden */
1541 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1542 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1544 /* Enabled now*/
1545 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1546 ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1548 /* GDI cursor unchanged */
1549 memset(&info, 0, sizeof(info));
1550 info.cbSize = sizeof(info);
1551 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1552 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
1553 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1555 refcount = IDirect3DDevice9_Release(device);
1556 ok(!refcount, "Device has %u references left.\n", refcount);
1557 cleanup:
1558 IDirect3D9_Release(d3d);
1559 DestroyWindow(window);
1562 static void test_reset(void)
1564 HRESULT hr;
1565 RECT winrect;
1566 D3DPRESENT_PARAMETERS d3dpp;
1567 D3DDISPLAYMODE d3ddm, d3ddm2;
1568 D3DVIEWPORT9 vp;
1569 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1570 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1571 IDirect3DSwapChain9 *pSwapchain;
1572 IDirect3DSurface9 *surface;
1573 IDirect3DTexture9 *texture;
1574 IDirect3DVertexShader9 *shader;
1575 UINT i, adapter_mode_count;
1576 D3DLOCKED_RECT lockrect;
1577 IDirect3DDevice9 *device1 = NULL;
1578 IDirect3DDevice9 *device2 = NULL;
1579 IDirect3D9 *d3d;
1580 D3DCAPS9 caps;
1581 DWORD value;
1582 HWND hwnd;
1583 struct
1585 UINT w;
1586 UINT h;
1587 } *modes = NULL;
1588 UINT mode_count = 0;
1590 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1591 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1592 ok(!!hwnd, "Failed to create a window.\n");
1593 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1594 ok(!!d3d, "Failed to create a D3D object.\n");
1596 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1597 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1598 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1599 for(i = 0; i < adapter_mode_count; ++i)
1601 UINT j;
1602 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1603 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1604 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1606 for (j = 0; j < mode_count; ++j)
1608 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1609 break;
1611 if (j == mode_count)
1613 modes[j].w = d3ddm2.Width;
1614 modes[j].h = d3ddm2.Height;
1615 ++mode_count;
1618 /* We use them as invalid modes */
1619 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1620 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1621 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1622 d3ddm2.Width, d3ddm2.Height);
1623 goto cleanup;
1627 if (mode_count < 2)
1629 skip("Less than 2 modes supported, skipping mode tests\n");
1630 goto cleanup;
1633 i = 0;
1634 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1636 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1637 d3dpp.Windowed = FALSE;
1638 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1639 d3dpp.BackBufferWidth = modes[i].w;
1640 d3dpp.BackBufferHeight = modes[i].h;
1641 d3dpp.BackBufferFormat = d3ddm.Format;
1642 d3dpp.EnableAutoDepthStencil = TRUE;
1643 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1645 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1646 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
1647 if (FAILED(hr))
1649 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
1650 goto cleanup;
1652 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1653 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1655 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1656 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1658 width = GetSystemMetrics(SM_CXSCREEN);
1659 height = GetSystemMetrics(SM_CYSCREEN);
1660 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1661 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1663 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1664 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1665 if(SUCCEEDED(hr))
1667 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1668 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1669 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1670 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1671 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1672 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1675 i = 1;
1676 vp.X = 10;
1677 vp.Y = 20;
1678 vp.MinZ = 2;
1679 vp.MaxZ = 3;
1680 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1681 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1683 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1684 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1685 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1686 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1687 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1689 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1690 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1691 d3dpp.Windowed = FALSE;
1692 d3dpp.BackBufferWidth = modes[i].w;
1693 d3dpp.BackBufferHeight = modes[i].h;
1694 d3dpp.BackBufferFormat = d3ddm.Format;
1695 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1696 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1697 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1698 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1700 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1701 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1702 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1704 ZeroMemory(&vp, sizeof(vp));
1705 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1706 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1707 if(SUCCEEDED(hr))
1709 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1710 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1711 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1712 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1713 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1714 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1717 width = GetSystemMetrics(SM_CXSCREEN);
1718 height = GetSystemMetrics(SM_CYSCREEN);
1719 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1720 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1722 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1723 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1724 if(SUCCEEDED(hr))
1726 ZeroMemory(&d3dpp, sizeof(d3dpp));
1727 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1728 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1729 if(SUCCEEDED(hr))
1731 ok(d3dpp.BackBufferWidth == modes[i].w, "Back buffer width is %u, expected %u\n",
1732 d3dpp.BackBufferWidth, modes[i].w);
1733 ok(d3dpp.BackBufferHeight == modes[i].h, "Back buffer height is %u, expected %u\n",
1734 d3dpp.BackBufferHeight, modes[i].h);
1736 IDirect3DSwapChain9_Release(pSwapchain);
1739 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1740 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1741 d3dpp.Windowed = TRUE;
1742 d3dpp.BackBufferWidth = 400;
1743 d3dpp.BackBufferHeight = 300;
1744 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1745 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1746 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1747 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1749 width = GetSystemMetrics(SM_CXSCREEN);
1750 height = GetSystemMetrics(SM_CYSCREEN);
1751 ok(width == orig_width, "Screen width is %d\n", width);
1752 ok(height == orig_height, "Screen height is %d\n", height);
1754 ZeroMemory(&vp, sizeof(vp));
1755 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1756 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1757 if(SUCCEEDED(hr))
1759 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1760 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1761 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1762 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1763 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1764 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1767 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1768 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1769 if(SUCCEEDED(hr))
1771 ZeroMemory(&d3dpp, sizeof(d3dpp));
1772 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1773 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1774 if(SUCCEEDED(hr))
1776 ok(d3dpp.BackBufferWidth == 400, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1777 ok(d3dpp.BackBufferHeight == 300, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1779 IDirect3DSwapChain9_Release(pSwapchain);
1782 winrect.left = 0;
1783 winrect.top = 0;
1784 winrect.right = 200;
1785 winrect.bottom = 150;
1786 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1787 ok(SetWindowPos(hwnd, NULL, 0, 0,
1788 winrect.right-winrect.left,
1789 winrect.bottom-winrect.top,
1790 SWP_NOMOVE|SWP_NOZORDER),
1791 "SetWindowPos failed\n");
1793 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1794 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1795 d3dpp.Windowed = TRUE;
1796 d3dpp.BackBufferWidth = 0;
1797 d3dpp.BackBufferHeight = 0;
1798 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1799 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1800 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1801 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1803 ZeroMemory(&vp, sizeof(vp));
1804 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1805 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1806 if(SUCCEEDED(hr))
1808 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1809 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1810 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
1811 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
1812 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1813 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1816 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1817 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1818 if(SUCCEEDED(hr))
1820 ZeroMemory(&d3dpp, sizeof(d3dpp));
1821 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1822 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1823 if(SUCCEEDED(hr))
1825 ok(d3dpp.BackBufferWidth == 200, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1826 ok(d3dpp.BackBufferHeight == 150, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1828 IDirect3DSwapChain9_Release(pSwapchain);
1831 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1832 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1833 d3dpp.Windowed = TRUE;
1834 d3dpp.BackBufferWidth = 400;
1835 d3dpp.BackBufferHeight = 300;
1837 /* _Reset fails if there is a resource in the default pool */
1838 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1839 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1840 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1841 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1842 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1843 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1844 IDirect3DSurface9_Release(surface);
1845 /* Reset again to get the device out of the lost state */
1846 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1847 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1848 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1849 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1851 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1853 IDirect3DVolumeTexture9 *volume_texture;
1855 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1856 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1857 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1858 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1859 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1860 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1861 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1862 hr, D3DERR_DEVICENOTRESET);
1863 IDirect3DVolumeTexture9_Release(volume_texture);
1864 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1865 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1866 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1867 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1869 else
1871 skip("Volume textures not supported.\n");
1874 /* Scratch, sysmem and managed pools are fine */
1875 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1876 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1877 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1878 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1879 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1880 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1881 IDirect3DSurface9_Release(surface);
1883 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1884 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1885 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1886 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1887 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1888 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1889 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1890 IDirect3DSurface9_Release(surface);
1892 /* The depth stencil should get reset to the auto depth stencil when present. */
1893 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
1894 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
1896 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1897 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1898 ok(surface == NULL, "Depth stencil should be NULL\n");
1900 d3dpp.EnableAutoDepthStencil = TRUE;
1901 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1902 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1903 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1905 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1906 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1907 ok(surface != NULL, "Depth stencil should not be NULL\n");
1908 if (surface) IDirect3DSurface9_Release(surface);
1910 d3dpp.EnableAutoDepthStencil = FALSE;
1911 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1912 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1914 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1915 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1916 ok(surface == NULL, "Depth stencil should be NULL\n");
1918 /* Will a sysmem or scratch survive while locked */
1919 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1920 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1921 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1922 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1923 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1924 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1925 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1926 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1927 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1928 IDirect3DSurface9_UnlockRect(surface);
1929 IDirect3DSurface9_Release(surface);
1931 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1932 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1933 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1934 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1935 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1936 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1937 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1938 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1939 IDirect3DSurface9_UnlockRect(surface);
1940 IDirect3DSurface9_Release(surface);
1942 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
1943 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
1944 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1945 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1946 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1947 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1948 IDirect3DTexture9_Release(texture);
1950 /* A reference held to an implicit surface causes failures as well */
1951 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1952 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
1953 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1954 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1955 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1956 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1957 IDirect3DSurface9_Release(surface);
1958 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1959 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1960 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1961 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1963 /* Shaders are fine as well */
1964 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
1965 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
1966 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1967 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1968 IDirect3DVertexShader9_Release(shader);
1970 /* Try setting invalid modes */
1971 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1972 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1973 d3dpp.Windowed = FALSE;
1974 d3dpp.BackBufferWidth = 32;
1975 d3dpp.BackBufferHeight = 32;
1976 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1977 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
1978 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1979 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1981 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1982 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1983 d3dpp.Windowed = FALSE;
1984 d3dpp.BackBufferWidth = 801;
1985 d3dpp.BackBufferHeight = 600;
1986 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1987 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
1988 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1989 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1991 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1992 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1993 d3dpp.Windowed = FALSE;
1994 d3dpp.BackBufferWidth = 0;
1995 d3dpp.BackBufferHeight = 0;
1996 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1997 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
1998 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1999 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2001 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2003 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2004 d3dpp.Windowed = TRUE;
2005 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2006 d3dpp.BackBufferFormat = d3ddm.Format;
2007 d3dpp.EnableAutoDepthStencil = FALSE;
2008 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2010 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2011 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2013 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2014 goto cleanup;
2017 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2018 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2020 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2021 d3dpp.Windowed = TRUE;
2022 d3dpp.BackBufferWidth = 400;
2023 d3dpp.BackBufferHeight = 300;
2024 d3dpp.EnableAutoDepthStencil = TRUE;
2025 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2027 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2028 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2030 if (FAILED(hr)) goto cleanup;
2032 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2033 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2034 ok(surface != NULL, "Depth stencil should not be NULL\n");
2035 if (surface) IDirect3DSurface9_Release(surface);
2037 cleanup:
2038 HeapFree(GetProcessHeap(), 0, modes);
2039 if (device2)
2041 UINT refcount = IDirect3DDevice9_Release(device2);
2042 ok(!refcount, "Device has %u references left.\n", refcount);
2044 if (device1)
2046 UINT refcount = IDirect3DDevice9_Release(device1);
2047 ok(!refcount, "Device has %u references left.\n", refcount);
2049 IDirect3D9_Release(d3d);
2050 DestroyWindow(hwnd);
2053 /* Test adapter display modes */
2054 static void test_display_modes(void)
2056 D3DDISPLAYMODE dmode;
2057 IDirect3D9 *d3d;
2059 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2060 ok(!!d3d, "Failed to create a D3D object.\n");
2062 #define TEST_FMT(x,r) do { \
2063 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2064 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2065 } while(0)
2067 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2068 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2069 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2070 /* D3DFMT_R5G6B5 */
2071 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2072 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2073 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2074 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2075 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2076 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2077 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2078 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2079 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2080 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2081 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2082 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2084 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2085 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2087 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2088 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2089 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2091 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2092 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2093 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2094 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2095 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2096 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2098 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2099 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2100 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2101 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2102 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2103 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2104 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2105 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2106 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2107 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2109 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2110 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2111 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2112 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2113 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2114 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2115 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2116 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2117 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2118 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2120 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2121 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2122 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2123 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2124 /* Floating point formats */
2125 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2126 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2127 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2129 /* IEEE formats */
2130 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2131 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2132 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2134 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2136 TEST_FMT(0, D3DERR_INVALIDCALL);
2138 IDirect3D9_Release(d3d);
2141 static void test_scene(void)
2143 IDirect3DSurface9 *surface1, *surface2, *surface3;
2144 IDirect3DSurface9 *backBuffer, *rt, *ds;
2145 RECT rect = {0, 0, 128, 128};
2146 IDirect3DDevice9 *device;
2147 IDirect3D9 *d3d;
2148 ULONG refcount;
2149 D3DCAPS9 caps;
2150 HWND window;
2151 HRESULT hr;
2153 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2154 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2155 ok(!!window, "Failed to create a window.\n");
2156 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2157 ok(!!d3d, "Failed to create a D3D object.\n");
2158 if (!(device = create_device(d3d, window, window, TRUE)))
2160 skip("Failed to create a 3D device, skipping test.\n");
2161 goto cleanup;
2164 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2165 memset(&caps, 0, sizeof(caps));
2166 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2167 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2169 /* Test an EndScene without BeginScene. Should return an error */
2170 hr = IDirect3DDevice9_EndScene(device);
2171 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2173 /* Test a normal BeginScene / EndScene pair, this should work */
2174 hr = IDirect3DDevice9_BeginScene(device);
2175 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2176 hr = IDirect3DDevice9_EndScene(device);
2177 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2179 /* Test another EndScene without having begun a new scene. Should return an error */
2180 hr = IDirect3DDevice9_EndScene(device);
2181 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2183 /* Two nested BeginScene and EndScene calls */
2184 hr = IDirect3DDevice9_BeginScene(device);
2185 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2186 hr = IDirect3DDevice9_BeginScene(device);
2187 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2188 hr = IDirect3DDevice9_EndScene(device);
2189 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2190 hr = IDirect3DDevice9_EndScene(device);
2191 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2193 /* Create some surfaces to test stretchrect between the scenes */
2194 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2195 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2196 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2197 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2198 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2199 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2200 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2201 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2202 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2203 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2204 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2205 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2207 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2208 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2209 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2210 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2212 /* First make sure a simple StretchRect call works */
2213 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2214 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2215 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2216 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2217 if (0) /* Disabled for now because it crashes in wine */
2219 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2220 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2221 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2224 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2225 * BeginScene - Endscene pair with normal surfaces and render targets, but
2226 * not depth stencil surfaces. */
2227 hr = IDirect3DDevice9_BeginScene(device);
2228 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2230 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2231 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2232 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2233 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2234 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2235 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2236 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2238 hr = IDirect3DDevice9_EndScene(device);
2239 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2241 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2242 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2243 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2245 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2246 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2247 hr = IDirect3DDevice9_BeginScene(device);
2248 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2249 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2250 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2251 hr = IDirect3DDevice9_EndScene(device);
2252 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2254 IDirect3DSurface9_Release(rt);
2255 IDirect3DSurface9_Release(ds);
2256 IDirect3DSurface9_Release(backBuffer);
2257 IDirect3DSurface9_Release(surface1);
2258 IDirect3DSurface9_Release(surface2);
2259 IDirect3DSurface9_Release(surface3);
2260 refcount = IDirect3DDevice9_Release(device);
2261 ok(!refcount, "Device has %u references left.\n", refcount);
2262 cleanup:
2263 IDirect3D9_Release(d3d);
2264 DestroyWindow(window);
2267 static void test_limits(void)
2269 IDirect3DTexture9 *texture;
2270 IDirect3DDevice9 *device;
2271 IDirect3D9 *d3d;
2272 unsigned int i;
2273 ULONG refcount;
2274 HWND window;
2275 HRESULT hr;
2277 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2278 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2279 ok(!!window, "Failed to create a window.\n");
2280 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2281 ok(!!d3d, "Failed to create a D3D object.\n");
2282 if (!(device = create_device(d3d, window, window, TRUE)))
2284 skip("Failed to create a 3D device, skipping test.\n");
2285 goto cleanup;
2288 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2289 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2291 /* There are 16 pixel samplers. We should be able to access all of them */
2292 for (i = 0; i < 16; ++i)
2294 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2295 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2296 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2297 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2298 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2299 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2302 /* Now test all 8 textures stage states */
2303 for (i = 0; i < 8; ++i)
2305 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2306 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2309 /* Investigations show that accessing higher samplers / textures stage
2310 * states does not return an error either. Writing to too high samplers
2311 * (approximately sampler 40) causes memory corruption in Windows, so
2312 * there is no bounds checking. */
2313 IDirect3DTexture9_Release(texture);
2314 refcount = IDirect3D9_Release(device);
2315 ok(!refcount, "Device has %u references left.\n", refcount);
2316 cleanup:
2317 IDirect3D9_Release(d3d);
2318 DestroyWindow(window);
2321 static void test_depthstenciltest(void)
2323 HRESULT hr;
2324 IDirect3DDevice9 *pDevice = NULL;
2325 D3DPRESENT_PARAMETERS d3dpp;
2326 D3DDISPLAYMODE d3ddm;
2327 IDirect3DSurface9 *pDepthStencil = NULL;
2328 IDirect3DSurface9 *pDepthStencil2 = NULL;
2329 IDirect3D9 *d3d;
2330 DWORD state;
2331 HWND hwnd;
2333 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2334 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2335 ok(!!hwnd, "Failed to create a window.\n");
2336 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2337 ok(!!d3d, "Failed to create a D3D object.\n");
2339 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2340 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2341 d3dpp.Windowed = TRUE;
2342 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2343 d3dpp.BackBufferWidth = 800;
2344 d3dpp.BackBufferHeight = 600;
2345 d3dpp.BackBufferFormat = d3ddm.Format;
2346 d3dpp.EnableAutoDepthStencil = TRUE;
2347 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2349 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2350 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2351 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2352 if(!pDevice)
2354 skip("Failed to create a d3d device\n");
2355 goto cleanup;
2358 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2359 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2361 /* Try to clear */
2362 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2363 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2365 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2366 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2368 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2369 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2370 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2371 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2373 /* This left the render states untouched! */
2374 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2375 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2376 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2377 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2378 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2379 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2380 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2381 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2382 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2383 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2384 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2385 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2387 /* This is supposed to fail now */
2388 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2389 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2391 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2392 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2394 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2395 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2397 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2398 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2399 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2401 /* Now it works again */
2402 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2403 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2405 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2406 if(pDevice) IDirect3D9_Release(pDevice);
2408 /* Now see if autodepthstencil disable is honored. First, without a format set */
2409 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2410 d3dpp.Windowed = TRUE;
2411 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2412 d3dpp.BackBufferWidth = 800;
2413 d3dpp.BackBufferHeight = 600;
2414 d3dpp.BackBufferFormat = d3ddm.Format;
2415 d3dpp.EnableAutoDepthStencil = FALSE;
2416 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2418 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2419 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2420 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2421 if(!pDevice)
2423 skip("Failed to create a d3d device\n");
2424 goto cleanup;
2427 pDepthStencil = NULL;
2428 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2429 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2430 if(pDepthStencil) {
2431 IDirect3DSurface9_Release(pDepthStencil);
2432 pDepthStencil = NULL;
2435 /* Check the depth test state */
2436 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2437 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2438 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2440 if(pDevice) IDirect3D9_Release(pDevice);
2442 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2443 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2444 d3dpp.Windowed = TRUE;
2445 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2446 d3dpp.BackBufferWidth = 800;
2447 d3dpp.BackBufferHeight = 600;
2448 d3dpp.BackBufferFormat = d3ddm.Format;
2449 d3dpp.EnableAutoDepthStencil = FALSE;
2450 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2452 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2453 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2454 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2455 if(!pDevice)
2457 skip("Failed to create a d3d device\n");
2458 goto cleanup;
2461 pDepthStencil = NULL;
2462 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2463 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2464 if(pDepthStencil) {
2465 IDirect3DSurface9_Release(pDepthStencil);
2466 pDepthStencil = NULL;
2469 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2470 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2471 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2473 cleanup:
2474 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2475 if (pDevice)
2477 UINT refcount = IDirect3D9_Release(pDevice);
2478 ok(!refcount, "Device has %u references left.\n", refcount);
2480 IDirect3D9_Release(d3d);
2481 DestroyWindow(hwnd);
2484 static void test_get_rt(void)
2486 IDirect3DSurface9 *backbuffer, *rt;
2487 IDirect3DDevice9 *device;
2488 IDirect3D9 *d3d9;
2489 D3DCAPS9 caps;
2490 HWND window;
2491 HRESULT hr;
2492 ULONG ref;
2493 UINT i;
2495 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2496 0, 0, 128, 128, 0, 0, 0, 0);
2497 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2498 ok(!!d3d9, "Failed to create a D3D object.\n");
2499 device = create_device(d3d9, window, window, TRUE);
2500 if (!device)
2502 skip("Failed to create a D3D device, skipping tests.\n");
2503 goto done;
2506 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2507 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2508 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2510 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2511 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2513 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2515 rt = backbuffer;
2516 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2517 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2518 ok(!rt, "Got rt %p.\n", rt);
2521 IDirect3DSurface9_Release(backbuffer);
2523 ref = IDirect3DDevice9_Release(device);
2524 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2525 done:
2526 IDirect3D9_Release(d3d9);
2527 DestroyWindow(window);
2530 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
2531 static void test_draw_indexed(void)
2533 static const struct {
2534 float position[3];
2535 DWORD color;
2536 } quad[] = {
2537 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2538 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2539 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2540 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2542 WORD indices[] = {0, 1, 2, 3, 0, 2};
2544 static const D3DVERTEXELEMENT9 decl_elements[] = {
2545 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2546 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2547 D3DDECL_END()
2550 IDirect3DVertexDeclaration9 *vertex_declaration;
2551 IDirect3DVertexBuffer9 *vertex_buffer;
2552 IDirect3DIndexBuffer9 *index_buffer;
2553 IDirect3DDevice9 *device;
2554 IDirect3D9 *d3d9;
2555 ULONG refcount;
2556 HWND window;
2557 HRESULT hr;
2558 void *ptr;
2560 window = CreateWindowA("d3d9_test_wc", "d3d9_test", 0,
2561 0, 0, 640, 480, 0, 0, 0, 0);
2562 ok(!!window, "Failed to create a window.\n");
2563 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2564 ok(!!d3d9, "Failed to create a D3D object.\n");
2565 if (!(device = create_device(d3d9, window, window, TRUE)))
2567 skip("Failed to create a 3D device, skipping test.\n");
2568 goto cleanup;
2571 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2572 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
2573 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2574 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2576 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2577 ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
2578 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2579 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
2580 memcpy(ptr, quad, sizeof(quad));
2581 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2582 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2583 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2584 ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
2586 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
2587 ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
2588 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2589 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
2590 memcpy(ptr, indices, sizeof(indices));
2591 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2592 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2593 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2594 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
2595 hr = IDirect3DDevice9_BeginScene(device);
2596 ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
2598 /* NULL index buffer. Should fail */
2599 hr = IDirect3DDevice9_SetIndices(device, NULL);
2600 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
2601 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2602 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2603 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
2604 hr, D3DERR_INVALIDCALL);
2606 /* Valid index buffer, NULL vertex declaration. Should fail */
2607 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2608 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
2609 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2610 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2611 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
2612 hr, D3DERR_INVALIDCALL);
2614 /* Valid index buffer and vertex declaration. Should succeed */
2615 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2616 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2617 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2618 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2619 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
2621 hr = IDirect3DDevice9_EndScene(device);
2622 ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2624 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2625 ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2627 IDirect3DVertexBuffer9_Release(vertex_buffer);
2628 IDirect3DIndexBuffer9_Release(index_buffer);
2629 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2630 refcount = IDirect3DDevice9_Release(device);
2631 ok(!refcount, "Device has %u references left.\n", refcount);
2632 cleanup:
2633 IDirect3D9_Release(d3d9);
2634 DestroyWindow(window);
2637 static void test_null_stream(void)
2639 IDirect3DVertexBuffer9 *buffer = NULL;
2640 IDirect3DDevice9 *device;
2641 IDirect3D9 *d3d9;
2642 ULONG refcount;
2643 HWND window;
2644 HRESULT hr;
2645 IDirect3DVertexShader9 *shader = NULL;
2646 IDirect3DVertexDeclaration9 *decl = NULL;
2647 static const DWORD shader_code[] =
2649 0xfffe0101, /* vs_1_1 */
2650 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2651 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2652 0x0000ffff /* end */
2654 static const D3DVERTEXELEMENT9 decl_elements[] = {
2655 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2656 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2657 D3DDECL_END()
2660 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2661 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2662 ok(!!window, "Failed to create a window.\n");
2663 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2664 ok(!!d3d9, "Failed to create a D3D object.\n");
2665 if (!(device = create_device(d3d9, window, window, TRUE)))
2667 skip("Failed to create a 3D device, skipping test.\n");
2668 goto cleanup;
2671 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2672 if(FAILED(hr)) {
2673 skip("No vertex shader support\n");
2674 goto cleanup;
2676 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2677 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2678 if (FAILED(hr)) {
2679 skip("Vertex declaration handling not possible.\n");
2680 goto cleanup;
2682 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2683 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2684 if (FAILED(hr)) {
2685 skip("Vertex buffer handling not possible.\n");
2686 goto cleanup;
2689 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
2690 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2691 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
2692 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2693 hr = IDirect3DDevice9_SetVertexShader(device, shader);
2694 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
2695 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2696 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
2698 hr = IDirect3DDevice9_BeginScene(device);
2699 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2700 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
2701 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2702 hr = IDirect3DDevice9_EndScene(device);
2703 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2705 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2706 IDirect3DDevice9_SetVertexShader(device, NULL);
2707 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2709 cleanup:
2710 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
2711 if (decl) IDirect3DVertexDeclaration9_Release(decl);
2712 if (shader) IDirect3DVertexShader9_Release(shader);
2713 if (device)
2715 refcount = IDirect3DDevice9_Release(device);
2716 ok(!refcount, "Device has %u references left.\n", refcount);
2718 IDirect3D9_Release(d3d9);
2719 DestroyWindow(window);
2722 static void test_lights(void)
2724 IDirect3DDevice9 *device;
2725 IDirect3D9 *d3d9;
2726 ULONG refcount;
2727 HWND window;
2728 HRESULT hr;
2729 unsigned int i;
2730 BOOL enabled;
2731 D3DCAPS9 caps;
2733 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2734 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2735 ok(!!window, "Failed to create a window.\n");
2736 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2737 ok(!!d3d9, "Failed to create a D3D object.\n");
2738 if (!(device = create_device(d3d9, window, window, TRUE)))
2740 skip("Failed to create a 3D device, skipping test.\n");
2741 goto cleanup;
2744 memset(&caps, 0, sizeof(caps));
2745 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2746 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
2748 for(i = 1; i <= caps.MaxActiveLights; i++) {
2749 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
2750 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2751 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
2752 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
2753 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2756 /* TODO: Test the rendering results in this situation */
2757 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
2758 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2759 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
2760 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2761 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2762 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
2763 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2765 for(i = 1; i <= caps.MaxActiveLights; i++) {
2766 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2767 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2770 refcount = IDirect3DDevice9_Release(device);
2771 ok(!refcount, "Device has %u references left.\n", refcount);
2772 cleanup:
2773 IDirect3D9_Release(d3d9);
2774 DestroyWindow(window);
2777 static void test_set_stream_source(void)
2779 IDirect3DVertexBuffer9 *vb;
2780 IDirect3DDevice9 *device;
2781 IDirect3D9 *d3d9;
2782 ULONG refcount;
2783 HWND window;
2784 HRESULT hr;
2786 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2787 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2788 ok(!!window, "Failed to create a window.\n");
2789 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2790 ok(!!d3d9, "Failed to create a D3D object.\n");
2791 if (!(device = create_device(d3d9, window, window, TRUE)))
2793 skip("Failed to create a 3D device, skipping test.\n");
2794 goto cleanup;
2797 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
2798 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
2800 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
2801 * (Radeon 9000 verified) reject them, so accept both results. Wine
2802 * currently rejects this to be able to optimize the vbo conversion, but
2803 * writes a WARN. */
2804 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
2805 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2806 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
2807 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2808 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
2809 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2810 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
2811 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2812 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
2813 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2815 /* Try to set the NULL buffer with an offset and stride 0 */
2816 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2817 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2818 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2819 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2820 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2821 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2822 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2823 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2824 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2825 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2827 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2828 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2830 IDirect3DVertexBuffer9_Release(vb);
2831 refcount = IDirect3DDevice9_Release(device);
2832 ok(!refcount, "Device has %u references left.\n", refcount);
2833 cleanup:
2834 IDirect3D9_Release(d3d9);
2835 DestroyWindow(window);
2838 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
2839 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
2840 * a fixed number of combinations are possible in fullscreen mode. In windowed
2841 * mode more combinations are allowed due to format conversion and this is
2842 * likely driver dependent. */
2843 static void test_display_formats(void)
2845 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
2846 unsigned int backbuffer, display;
2847 unsigned int windowed;
2848 IDirect3D9 *d3d9;
2849 BOOL should_pass;
2850 BOOL has_modes;
2851 HRESULT hr;
2853 static const struct
2855 const char *name;
2856 D3DFORMAT format;
2857 D3DFORMAT alpha_format;
2858 BOOL display;
2859 BOOL windowed;
2861 formats[] =
2863 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
2864 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
2865 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
2866 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
2867 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
2868 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
2869 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
2872 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2873 ok(!!d3d9, "Failed to create a D3D object.\n");
2875 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
2877 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
2879 for (windowed = 0; windowed <= 1; ++windowed)
2881 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
2883 should_pass = FALSE;
2885 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
2887 D3DFORMAT backbuffer_format;
2889 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
2890 backbuffer_format = formats[display].format;
2891 else
2892 backbuffer_format = formats[backbuffer].format;
2894 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
2895 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
2896 if (hr == D3D_OK)
2898 if (windowed)
2900 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
2901 backbuffer_format, formats[display].format);
2902 should_pass = (hr == D3D_OK);
2904 else
2905 should_pass = (formats[display].format == formats[backbuffer].format
2906 || (formats[display].alpha_format
2907 && formats[display].alpha_format == formats[backbuffer].alpha_format));
2911 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
2912 formats[display].format, formats[backbuffer].format, windowed);
2913 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
2914 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
2915 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
2920 IDirect3D9_Release(d3d9);
2923 static void test_scissor_size(void)
2925 IDirect3D9 *d3d9_ptr;
2926 unsigned int i;
2927 static struct {
2928 int winx; int winy; int backx; int backy; BOOL window;
2929 } scts[] = { /* scissor tests */
2930 {800, 600, 640, 480, TRUE},
2931 {800, 600, 640, 480, FALSE},
2932 {640, 480, 800, 600, TRUE},
2933 {640, 480, 800, 600, FALSE},
2936 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
2937 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
2939 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
2940 IDirect3DDevice9 *device_ptr = 0;
2941 D3DPRESENT_PARAMETERS present_parameters;
2942 HRESULT hr;
2943 HWND hwnd = 0;
2944 RECT scissorrect;
2946 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
2947 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
2949 if (!scts[i].window)
2951 scts[i].backx = screen_width;
2952 scts[i].backy = screen_height;
2955 ZeroMemory(&present_parameters, sizeof(present_parameters));
2956 present_parameters.Windowed = scts[i].window;
2957 present_parameters.hDeviceWindow = hwnd;
2958 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2959 present_parameters.BackBufferWidth = scts[i].backx;
2960 present_parameters.BackBufferHeight = scts[i].backy;
2961 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
2962 present_parameters.EnableAutoDepthStencil = TRUE;
2963 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2965 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2966 if(FAILED(hr)) {
2967 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
2968 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2969 if(FAILED(hr)) {
2970 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2973 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
2975 if (!device_ptr)
2977 DestroyWindow(hwnd);
2978 skip("Creating the device failed\n");
2979 goto err_out;
2982 /* Check for the default scissor rect size */
2983 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2984 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2985 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy && scissorrect.top == 0 && scissorrect.left == 0, "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom, scts[i].backx, scts[i].backy);
2987 /* check the scissorrect values after a reset */
2988 present_parameters.BackBufferWidth = screen_width;
2989 present_parameters.BackBufferHeight = screen_height;
2990 hr = IDirect3DDevice9_Reset(device_ptr, &present_parameters);
2991 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2992 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
2993 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2995 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2996 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2997 ok(scissorrect.right == screen_width && scissorrect.bottom == screen_height && scissorrect.top == 0 && scissorrect.left == 0, "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom, screen_width, screen_height);
2999 if(device_ptr) {
3000 ULONG ref;
3002 ref = IDirect3DDevice9_Release(device_ptr);
3003 DestroyWindow(hwnd);
3004 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3008 err_out:
3009 IDirect3D9_Release(d3d9_ptr);
3012 static void test_multi_device(void)
3014 IDirect3DDevice9 *device1, *device2;
3015 HWND window1, window2;
3016 IDirect3D9 *d3d9;
3017 ULONG refcount;
3019 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3020 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3021 ok(!!window1, "Failed to create a window.\n");
3022 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3023 ok(!!d3d9, "Failed to create a D3D object.\n");
3024 if (!(device1 = create_device(d3d9, window1, window1, TRUE)))
3026 skip("Failed to create a 3D device, skipping test.\n");
3027 IDirect3D9_Release(d3d9);
3028 DestroyWindow(window1);
3029 return;
3031 IDirect3D9_Release(d3d9);
3033 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3034 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3035 ok(!!window2, "Failed to create a window.\n");
3036 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3037 ok(!!d3d9, "Failed to create a D3D object.\n");
3038 device2 = create_device(d3d9, window2, window2, TRUE);
3039 IDirect3D9_Release(d3d9);
3041 refcount = IDirect3DDevice9_Release(device2);
3042 ok(!refcount, "Device has %u references left.\n", refcount);
3043 refcount = IDirect3DDevice9_Release(device1);
3044 ok(!refcount, "Device has %u references left.\n", refcount);
3045 DestroyWindow(window2);
3046 DestroyWindow(window1);
3049 static HWND filter_messages;
3051 enum message_window
3053 DEVICE_WINDOW,
3054 FOCUS_WINDOW,
3057 struct message
3059 UINT message;
3060 enum message_window window;
3063 static const struct message *expect_messages;
3064 static HWND device_window, focus_window;
3066 struct wndproc_thread_param
3068 HWND dummy_window;
3069 HANDLE window_created;
3070 HANDLE test_finished;
3071 BOOL running_in_foreground;
3074 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3076 if (filter_messages && filter_messages == hwnd)
3078 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3079 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3082 if (expect_messages)
3084 HWND w;
3086 switch (expect_messages->window)
3088 case DEVICE_WINDOW:
3089 w = device_window;
3090 break;
3092 case FOCUS_WINDOW:
3093 w = focus_window;
3094 break;
3096 default:
3097 w = NULL;
3098 break;
3101 if (hwnd == w && expect_messages->message == message) ++expect_messages;
3104 return DefWindowProcA(hwnd, message, wparam, lparam);
3107 static DWORD WINAPI wndproc_thread(void *param)
3109 struct wndproc_thread_param *p = param;
3110 DWORD res;
3111 BOOL ret;
3113 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3114 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3115 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3117 ret = SetEvent(p->window_created);
3118 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3120 for (;;)
3122 MSG msg;
3124 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3125 res = WaitForSingleObject(p->test_finished, 100);
3126 if (res == WAIT_OBJECT_0) break;
3127 if (res != WAIT_TIMEOUT)
3129 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3130 break;
3134 DestroyWindow(p->dummy_window);
3136 return 0;
3139 static void test_wndproc(void)
3141 struct wndproc_thread_param thread_params;
3142 IDirect3DDevice9 *device;
3143 WNDCLASSA wc = {0};
3144 IDirect3D9 *d3d9;
3145 HANDLE thread;
3146 LONG_PTR proc;
3147 ULONG ref;
3148 DWORD res, tid;
3149 HWND tmp;
3151 static const struct message messages[] =
3153 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW},
3154 {WM_ACTIVATE, FOCUS_WINDOW},
3155 {WM_SETFOCUS, FOCUS_WINDOW},
3156 {0, 0},
3159 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3160 ok(!!d3d9, "Failed to create a D3D object.\n");
3162 wc.lpfnWndProc = test_proc;
3163 wc.lpszClassName = "d3d9_test_wndproc_wc";
3164 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3166 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3167 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3168 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3169 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3171 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3172 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3173 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3174 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3175 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3176 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3178 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3179 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3181 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3182 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3183 (LONG_PTR)test_proc, proc);
3184 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3185 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3186 (LONG_PTR)test_proc, proc);
3188 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3189 device_window, focus_window, thread_params.dummy_window);
3191 tmp = GetFocus();
3192 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3193 if (thread_params.running_in_foreground)
3195 tmp = GetForegroundWindow();
3196 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3197 thread_params.dummy_window, tmp);
3199 else
3200 skip("Not running in foreground, skip foreground window test\n");
3202 flush_events();
3204 expect_messages = messages;
3206 device = create_device(d3d9, device_window, focus_window, FALSE);
3207 if (!device)
3209 skip("Failed to create a D3D device, skipping tests.\n");
3210 goto done;
3213 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3214 expect_messages->message, expect_messages->window);
3215 expect_messages = NULL;
3217 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3219 tmp = GetFocus();
3220 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3221 tmp = GetForegroundWindow();
3222 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3224 SetForegroundWindow(focus_window);
3225 flush_events();
3227 filter_messages = focus_window;
3229 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3230 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3231 (LONG_PTR)test_proc, proc);
3233 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3234 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3235 (LONG_PTR)test_proc, proc);
3237 ref = IDirect3DDevice9_Release(device);
3238 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3240 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3241 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3242 (LONG_PTR)test_proc, proc);
3244 device = create_device(d3d9, focus_window, focus_window, FALSE);
3245 if (!device)
3247 skip("Failed to create a D3D device, skipping tests.\n");
3248 goto done;
3251 ref = IDirect3DDevice9_Release(device);
3252 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3254 device = create_device(d3d9, device_window, focus_window, FALSE);
3255 if (!device)
3257 skip("Failed to create a D3D device, skipping tests.\n");
3258 goto done;
3261 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3262 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3263 (LONG_PTR)test_proc, proc);
3265 ref = IDirect3DDevice9_Release(device);
3266 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3268 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3269 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3270 (LONG_PTR)DefWindowProcA, proc);
3272 done:
3273 filter_messages = NULL;
3274 IDirect3D9_Release(d3d9);
3276 SetEvent(thread_params.test_finished);
3277 WaitForSingleObject(thread, INFINITE);
3278 CloseHandle(thread_params.test_finished);
3279 CloseHandle(thread_params.window_created);
3280 CloseHandle(thread);
3282 DestroyWindow(device_window);
3283 DestroyWindow(focus_window);
3284 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3287 static void test_wndproc_windowed(void)
3289 struct wndproc_thread_param thread_params;
3290 IDirect3DDevice9 *device;
3291 WNDCLASSA wc = {0};
3292 IDirect3D9 *d3d9;
3293 HANDLE thread;
3294 LONG_PTR proc;
3295 HRESULT hr;
3296 ULONG ref;
3297 DWORD res, tid;
3298 HWND tmp;
3300 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3301 ok(!!d3d9, "Failed to create a D3D object.\n");
3303 wc.lpfnWndProc = test_proc;
3304 wc.lpszClassName = "d3d9_test_wndproc_wc";
3305 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3307 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3308 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3309 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3310 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3312 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3313 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3314 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3315 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3316 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3317 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3319 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3320 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3322 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3323 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3324 (LONG_PTR)test_proc, proc);
3325 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3326 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3327 (LONG_PTR)test_proc, proc);
3329 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3330 device_window, focus_window, thread_params.dummy_window);
3332 tmp = GetFocus();
3333 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3334 if (thread_params.running_in_foreground)
3336 tmp = GetForegroundWindow();
3337 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3338 thread_params.dummy_window, tmp);
3340 else
3341 skip("Not running in foreground, skip foreground window test\n");
3343 filter_messages = focus_window;
3345 device = create_device(d3d9, device_window, focus_window, TRUE);
3346 if (!device)
3348 skip("Failed to create a D3D device, skipping tests.\n");
3349 goto done;
3352 tmp = GetFocus();
3353 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3354 tmp = GetForegroundWindow();
3355 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3356 thread_params.dummy_window, tmp);
3358 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3359 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3360 (LONG_PTR)test_proc, proc);
3362 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3363 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3364 (LONG_PTR)test_proc, proc);
3366 filter_messages = NULL;
3368 hr = reset_device(device, device_window, FALSE);
3369 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3371 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3372 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3373 (LONG_PTR)test_proc, proc);
3375 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3376 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3377 (LONG_PTR)test_proc, proc);
3379 hr = reset_device(device, device_window, TRUE);
3380 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3382 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3383 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3384 (LONG_PTR)test_proc, proc);
3386 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3387 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3388 (LONG_PTR)test_proc, proc);
3390 filter_messages = focus_window;
3392 ref = IDirect3DDevice9_Release(device);
3393 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3395 filter_messages = device_window;
3397 device = create_device(d3d9, focus_window, focus_window, TRUE);
3398 if (!device)
3400 skip("Failed to create a D3D device, skipping tests.\n");
3401 goto done;
3404 filter_messages = NULL;
3406 hr = reset_device(device, focus_window, FALSE);
3407 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3409 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3410 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3411 (LONG_PTR)test_proc, proc);
3413 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3414 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3415 (LONG_PTR)test_proc, proc);
3417 hr = reset_device(device, focus_window, TRUE);
3418 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3420 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3421 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3422 (LONG_PTR)test_proc, proc);
3424 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3425 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3426 (LONG_PTR)test_proc, proc);
3428 filter_messages = device_window;
3430 ref = IDirect3DDevice9_Release(device);
3431 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3433 device = create_device(d3d9, device_window, focus_window, TRUE);
3434 if (!device)
3436 skip("Failed to create a D3D device, skipping tests.\n");
3437 goto done;
3440 filter_messages = NULL;
3442 hr = reset_device(device, device_window, FALSE);
3443 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3445 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3446 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3447 (LONG_PTR)test_proc, proc);
3449 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3450 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3451 (LONG_PTR)test_proc, proc);
3453 hr = reset_device(device, device_window, TRUE);
3454 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3456 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3457 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3458 (LONG_PTR)test_proc, proc);
3460 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3461 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3462 (LONG_PTR)test_proc, proc);
3464 filter_messages = device_window;
3466 ref = IDirect3DDevice9_Release(device);
3467 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3469 done:
3470 filter_messages = NULL;
3471 IDirect3D9_Release(d3d9);
3473 SetEvent(thread_params.test_finished);
3474 WaitForSingleObject(thread, INFINITE);
3475 CloseHandle(thread_params.test_finished);
3476 CloseHandle(thread_params.window_created);
3477 CloseHandle(thread);
3479 DestroyWindow(device_window);
3480 DestroyWindow(focus_window);
3481 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3484 static void test_reset_fullscreen(void)
3486 WNDCLASSEXA wc = {0};
3487 IDirect3DDevice9 *device = NULL;
3488 IDirect3D9 *d3d;
3489 ATOM atom;
3490 static const struct message messages[] =
3492 {WM_ACTIVATEAPP, FOCUS_WINDOW},
3493 {0, 0},
3496 d3d = Direct3DCreate9(D3D_SDK_VERSION);
3497 ok(!!d3d, "Failed to create a D3D object.\n");
3498 expect_messages = messages;
3500 wc.cbSize = sizeof(wc);
3501 wc.lpfnWndProc = test_proc;
3502 wc.lpszClassName = "test_reset_fullscreen";
3504 atom = RegisterClassExA(&wc);
3505 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
3507 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
3508 0, 0, screen_width, screen_height, NULL, NULL, NULL, NULL);
3509 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
3512 * Create a device in windowed mode.
3513 * Since the device is windowed and we haven't called any methods that
3514 * could show the window (such as ShowWindow or SetWindowPos) yet,
3515 * WM_ACTIVATEAPP will not have been sent.
3517 device = create_device(d3d, device_window, focus_window, TRUE);
3518 if (!device)
3520 skip("Unable to create device. Skipping test.\n");
3521 goto cleanup;
3525 * Switch to fullscreen mode.
3526 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
3527 * message to be sent.
3529 ok(SUCCEEDED(reset_device(device, device_window, FALSE)), "Failed to reset device.\n");
3531 flush_events();
3532 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
3533 expect_messages = NULL;
3535 cleanup:
3536 if (device) IDirect3DDevice9_Release(device);
3537 IDirect3D9_Release(d3d);
3538 DestroyWindow(device_window);
3539 device_window = focus_window = NULL;
3540 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
3544 static inline void set_fpu_cw(WORD cw)
3546 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3547 #define D3D9_TEST_SET_FPU_CW 1
3548 __asm__ volatile ("fnclex");
3549 __asm__ volatile ("fldcw %0" : : "m" (cw));
3550 #elif defined(__i386__) && defined(_MSC_VER)
3551 #define D3D9_TEST_SET_FPU_CW 1
3552 __asm fnclex;
3553 __asm fldcw cw;
3554 #endif
3557 static inline WORD get_fpu_cw(void)
3559 WORD cw = 0;
3560 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3561 #define D3D9_TEST_GET_FPU_CW 1
3562 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3563 #elif defined(__i386__) && defined(_MSC_VER)
3564 #define D3D9_TEST_GET_FPU_CW 1
3565 __asm fnstcw cw;
3566 #endif
3567 return cw;
3570 static void test_fpu_setup(void)
3572 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
3573 D3DPRESENT_PARAMETERS present_parameters;
3574 IDirect3DDevice9 *device;
3575 HWND window = NULL;
3576 IDirect3D9 *d3d9;
3577 HRESULT hr;
3578 WORD cw;
3580 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3581 ok(!!window, "Failed to create a window.\n");
3582 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3583 ok(!!d3d9, "Failed to create a D3D object.\n");
3585 memset(&present_parameters, 0, sizeof(present_parameters));
3586 present_parameters.Windowed = TRUE;
3587 present_parameters.hDeviceWindow = window;
3588 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
3590 set_fpu_cw(0xf60);
3591 cw = get_fpu_cw();
3592 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3594 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3595 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
3596 if (FAILED(hr))
3598 skip("Failed to create a device, hr %#x.\n", hr);
3599 set_fpu_cw(0x37f);
3600 goto done;
3603 cw = get_fpu_cw();
3604 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3606 IDirect3DDevice9_Release(device);
3608 cw = get_fpu_cw();
3609 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3610 set_fpu_cw(0xf60);
3611 cw = get_fpu_cw();
3612 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3614 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3615 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
3616 ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
3618 cw = get_fpu_cw();
3619 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3620 set_fpu_cw(0x37f);
3622 IDirect3DDevice9_Release(device);
3624 done:
3625 IDirect3D9_Release(d3d9);
3626 DestroyWindow(window);
3627 #endif
3630 static void test_window_style(void)
3632 RECT focus_rect, fullscreen_rect, r;
3633 LONG device_style, device_exstyle;
3634 LONG focus_style, focus_exstyle;
3635 LONG style, expected_style;
3636 IDirect3DDevice9 *device;
3637 IDirect3D9 *d3d9;
3638 HRESULT hr;
3639 ULONG ref;
3641 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3642 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3643 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3644 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3645 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3646 ok(!!d3d9, "Failed to create a D3D object.\n");
3648 device_style = GetWindowLongA(device_window, GWL_STYLE);
3649 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3650 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3651 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3653 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3654 GetWindowRect(focus_window, &focus_rect);
3656 device = create_device(d3d9, device_window, focus_window, FALSE);
3657 if (!device)
3659 skip("Failed to create a D3D device, skipping tests.\n");
3660 goto done;
3663 style = GetWindowLongA(device_window, GWL_STYLE);
3664 expected_style = device_style | WS_VISIBLE;
3665 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3666 expected_style, style);
3667 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3668 expected_style = device_exstyle | WS_EX_TOPMOST;
3669 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3670 expected_style, style);
3672 style = GetWindowLongA(focus_window, GWL_STYLE);
3673 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3674 focus_style, style);
3675 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3676 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3677 focus_exstyle, style);
3679 GetWindowRect(device_window, &r);
3680 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3681 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3682 r.left, r.top, r.right, r.bottom);
3683 GetClientRect(device_window, &r);
3684 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3685 GetWindowRect(focus_window, &r);
3686 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3687 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3688 r.left, r.top, r.right, r.bottom);
3690 hr = reset_device(device, device_window, TRUE);
3691 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3693 style = GetWindowLongA(device_window, GWL_STYLE);
3694 expected_style = device_style | WS_VISIBLE;
3695 ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3696 expected_style, style);
3697 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3698 expected_style = device_exstyle | WS_EX_TOPMOST;
3699 ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3700 expected_style, style);
3702 style = GetWindowLongA(focus_window, GWL_STYLE);
3703 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3704 focus_style, style);
3705 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3706 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3707 focus_exstyle, style);
3709 ref = IDirect3DDevice9_Release(device);
3710 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3712 done:
3713 IDirect3D9_Release(d3d9);
3715 DestroyWindow(device_window);
3716 DestroyWindow(focus_window);
3719 static const POINT *expect_pos;
3721 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
3723 if (message == WM_MOUSEMOVE)
3725 if (expect_pos && expect_pos->x && expect_pos->y)
3727 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
3729 ClientToScreen(window, &p);
3730 if (expect_pos->x == p.x && expect_pos->y == p.y)
3731 ++expect_pos;
3735 return DefWindowProcA(window, message, wparam, lparam);
3738 static void test_cursor_pos(void)
3740 IDirect3DSurface9 *cursor;
3741 IDirect3DDevice9 *device;
3742 WNDCLASSA wc = {0};
3743 IDirect3D9 *d3d9;
3744 UINT refcount;
3745 HWND window;
3746 HRESULT hr;
3747 BOOL ret;
3749 /* Note that we don't check for movement we're not supposed to receive.
3750 * That's because it's hard to distinguish from the user accidentally
3751 * moving the mouse. */
3752 static const POINT points[] =
3754 {50, 50},
3755 {75, 75},
3756 {100, 100},
3757 {125, 125},
3758 {150, 150},
3759 {125, 125},
3760 {150, 150},
3761 {150, 150},
3762 {0, 0},
3765 wc.lpfnWndProc = test_cursor_proc;
3766 wc.lpszClassName = "d3d9_test_cursor_wc";
3767 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3768 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3769 0, 0, 320, 240, NULL, NULL, NULL, NULL);
3770 ShowWindow(window, SW_SHOW);
3771 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3772 ok(!!d3d9, "Failed to create a D3D object.\n");
3774 device = create_device(d3d9, window, window, TRUE);
3775 if (!device)
3777 skip("Failed to create a D3D device, skipping tests.\n");
3778 goto done;
3781 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
3782 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
3783 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
3784 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
3785 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
3786 IDirect3DSurface9_Release(cursor);
3787 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
3788 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
3790 flush_events();
3791 expect_pos = points;
3793 ret = SetCursorPos(50, 50);
3794 ok(ret, "Failed to set cursor position.\n");
3795 flush_events();
3797 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3798 flush_events();
3799 /* SetCursorPosition() eats duplicates. */
3800 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3801 flush_events();
3803 ret = SetCursorPos(100, 100);
3804 ok(ret, "Failed to set cursor position.\n");
3805 flush_events();
3806 /* Even if the position was set with SetCursorPos(). */
3807 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
3808 flush_events();
3810 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3811 flush_events();
3812 ret = SetCursorPos(150, 150);
3813 ok(ret, "Failed to set cursor position.\n");
3814 flush_events();
3815 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3816 flush_events();
3818 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
3819 flush_events();
3820 /* SetCursorPos() doesn't. */
3821 ret = SetCursorPos(150, 150);
3822 ok(ret, "Failed to set cursor position.\n");
3823 flush_events();
3825 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
3826 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
3828 refcount = IDirect3DDevice9_Release(device);
3829 ok(!refcount, "Device has %u references left.\n", refcount);
3830 done:
3831 DestroyWindow(window);
3832 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
3833 IDirect3D9_Release(d3d9);
3836 static void test_mode_change(void)
3838 RECT fullscreen_rect, focus_rect, r;
3839 IDirect3DSurface9 *backbuffer;
3840 IDirect3DDevice9 *device;
3841 D3DSURFACE_DESC desc;
3842 IDirect3D9 *d3d9;
3843 DEVMODEW devmode;
3844 UINT refcount;
3845 HRESULT hr;
3846 DWORD ret;
3848 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3849 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3850 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3851 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3852 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3853 ok(!!d3d9, "Failed to create a D3D object.\n");
3855 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3856 GetWindowRect(focus_window, &focus_rect);
3858 device = create_device(d3d9, device_window, focus_window, FALSE);
3859 if (!device)
3861 skip("Failed to create a D3D device, skipping tests.\n");
3862 goto done;
3865 memset(&devmode, 0, sizeof(devmode));
3866 devmode.dmSize = sizeof(devmode);
3867 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3868 devmode.dmPelsWidth = 640;
3869 devmode.dmPelsHeight = 480;
3871 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3872 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3874 memset(&devmode, 0, sizeof(devmode));
3875 devmode.dmSize = sizeof(devmode);
3876 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3877 ok(ret, "Failed to get display mode.\n");
3878 ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3879 ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3881 GetWindowRect(device_window, &r);
3882 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3883 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3884 r.left, r.top, r.right, r.bottom);
3885 GetWindowRect(focus_window, &r);
3886 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3887 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3888 r.left, r.top, r.right, r.bottom);
3890 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3891 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3892 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
3893 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3894 ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3895 ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3896 IDirect3DSurface9_Release(backbuffer);
3898 refcount = IDirect3DDevice9_Release(device);
3899 ok(!refcount, "Device has %u references left.\n", refcount);
3901 memset(&devmode, 0, sizeof(devmode));
3902 devmode.dmSize = sizeof(devmode);
3903 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3904 ok(ret, "Failed to get display mode.\n");
3905 ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3906 ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3908 done:
3909 DestroyWindow(device_window);
3910 DestroyWindow(focus_window);
3911 IDirect3D9_Release(d3d9);
3913 memset(&devmode, 0, sizeof(devmode));
3914 devmode.dmSize = sizeof(devmode);
3915 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3916 ok(ret, "Failed to get display mode.\n");
3917 ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3918 ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3921 static void test_device_window_reset(void)
3923 RECT fullscreen_rect, device_rect, r;
3924 IDirect3DDevice9 *device;
3925 WNDCLASSA wc = {0};
3926 IDirect3D9 *d3d9;
3927 LONG_PTR proc;
3928 HRESULT hr;
3929 ULONG ref;
3931 wc.lpfnWndProc = test_proc;
3932 wc.lpszClassName = "d3d9_test_wndproc_wc";
3933 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3935 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3936 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3937 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3938 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3939 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3940 ok(!!d3d9, "Failed to create a D3D object.\n");
3942 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3943 GetWindowRect(device_window, &device_rect);
3945 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3946 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3947 (LONG_PTR)test_proc, proc);
3948 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3949 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3950 (LONG_PTR)test_proc, proc);
3952 device = create_device(d3d9, NULL, focus_window, FALSE);
3953 if (!device)
3955 skip("Failed to create a D3D device, skipping tests.\n");
3956 goto done;
3959 GetWindowRect(focus_window, &r);
3960 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3961 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3962 r.left, r.top, r.right, r.bottom);
3963 GetWindowRect(device_window, &r);
3964 ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3965 device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3966 r.left, r.top, r.right, r.bottom);
3968 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3969 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3970 (LONG_PTR)test_proc, proc);
3971 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3972 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3973 (LONG_PTR)test_proc, proc);
3975 hr = reset_device(device, device_window, FALSE);
3976 ok(SUCCEEDED(hr), "Failed to reset device.\n");
3978 GetWindowRect(focus_window, &r);
3979 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3980 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3981 r.left, r.top, r.right, r.bottom);
3982 GetWindowRect(device_window, &r);
3983 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3984 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3985 r.left, r.top, r.right, r.bottom);
3987 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3988 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3989 (LONG_PTR)test_proc, proc);
3990 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3991 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3992 (LONG_PTR)test_proc, proc);
3994 ref = IDirect3DDevice9_Release(device);
3995 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3997 done:
3998 IDirect3D9_Release(d3d9);
3999 DestroyWindow(device_window);
4000 DestroyWindow(focus_window);
4001 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4004 static void test_reset_resources(void)
4006 IDirect3DSurface9 *surface, *rt;
4007 IDirect3DTexture9 *texture;
4008 IDirect3DDevice9 *device;
4009 IDirect3D9 *d3d9;
4010 unsigned int i;
4011 D3DCAPS9 caps;
4012 HWND window;
4013 HRESULT hr;
4014 ULONG ref;
4016 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
4017 0, 0, 640, 480, 0, 0, 0, 0);
4018 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4019 ok(!!d3d9, "Failed to create a D3D object.\n");
4021 if (!(device = create_device(d3d9, window, window, TRUE)))
4023 skip("Failed to create a D3D device, skipping tests.\n");
4024 goto done;
4027 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4028 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4030 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
4031 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
4032 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
4033 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
4034 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
4035 IDirect3DSurface9_Release(surface);
4037 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
4039 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
4040 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4041 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
4042 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4043 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
4044 IDirect3DTexture9_Release(texture);
4045 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
4046 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
4047 IDirect3DSurface9_Release(surface);
4050 hr = reset_device(device, device_window, TRUE);
4051 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4053 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
4054 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
4055 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4056 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4057 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
4058 IDirect3DSurface9_Release(surface);
4059 IDirect3DSurface9_Release(rt);
4061 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
4063 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
4064 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4067 ref = IDirect3DDevice9_Release(device);
4068 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4070 done:
4071 IDirect3D9_Release(d3d9);
4072 DestroyWindow(window);
4075 static void test_set_rt_vp_scissor(void)
4077 IDirect3DStateBlock9 *stateblock;
4078 IDirect3DDevice9 *device;
4079 IDirect3DSurface9 *rt;
4080 IDirect3D9 *d3d9;
4081 D3DVIEWPORT9 vp;
4082 UINT refcount;
4083 HWND window;
4084 HRESULT hr;
4085 RECT rect;
4087 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
4088 0, 0, 640, 480, 0, 0, 0, 0);
4089 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4090 ok(!!d3d9, "Failed to create a D3D object.\n");
4091 if (!(device = create_device(d3d9, window, window, TRUE)))
4093 skip("Failed to create a D3D device, skipping tests.\n");
4094 DestroyWindow(window);
4095 return;
4098 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
4099 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
4100 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4102 hr = IDirect3DDevice9_GetViewport(device, &vp);
4103 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4104 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4105 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4106 ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
4107 ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
4108 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4109 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4111 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4112 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4113 ok(rect.left == 0 && rect.top == 0 && rect.right == screen_width && rect.bottom == screen_height,
4114 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4115 rect.left, rect.top, rect.right, rect.bottom);
4117 hr = IDirect3DDevice9_BeginStateBlock(device);
4118 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
4120 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4121 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4123 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
4124 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
4125 IDirect3DStateBlock9_Release(stateblock);
4127 hr = IDirect3DDevice9_GetViewport(device, &vp);
4128 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4129 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4130 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4131 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4132 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4133 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4134 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4136 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4137 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4138 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
4139 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4140 rect.left, rect.top, rect.right, rect.bottom);
4142 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4143 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4145 vp.X = 10;
4146 vp.Y = 20;
4147 vp.Width = 30;
4148 vp.Height = 40;
4149 vp.MinZ = 0.25f;
4150 vp.MaxZ = 0.75f;
4151 hr = IDirect3DDevice9_SetViewport(device, &vp);
4152 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
4154 SetRect(&rect, 50, 60, 70, 80);
4155 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
4156 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
4158 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4159 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4161 hr = IDirect3DDevice9_GetViewport(device, &vp);
4162 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4163 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4164 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4165 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4166 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4167 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4168 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4170 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4171 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4172 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
4173 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4174 rect.left, rect.top, rect.right, rect.bottom);
4176 IDirect3DSurface9_Release(rt);
4177 refcount = IDirect3DDevice9_Release(device);
4178 ok(!refcount, "Device has %u references left.\n", refcount);
4179 IDirect3D9_Release(d3d9);
4180 DestroyWindow(window);
4183 static void test_volume_get_container(void)
4185 IDirect3DVolumeTexture9 *texture = NULL;
4186 IDirect3DVolume9 *volume = NULL;
4187 IDirect3DDevice9 *device;
4188 IUnknown *container;
4189 IDirect3D9 *d3d9;
4190 ULONG refcount;
4191 D3DCAPS9 caps;
4192 HWND window;
4193 HRESULT hr;
4195 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4196 0, 0, 640, 480, 0, 0, 0, 0);
4197 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4198 ok(!!d3d9, "Failed to create a D3D object.\n");
4199 if (!(device = create_device(d3d9, window, window, TRUE)))
4201 skip("Failed to create a D3D device, skipping tests.\n");
4202 IDirect3D9_Release(d3d9);
4203 DestroyWindow(window);
4204 return;
4207 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4208 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4209 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
4211 skip("No volume texture support, skipping tests.\n");
4212 IDirect3DDevice9_Release(device);
4213 IDirect3D9_Release(d3d9);
4214 DestroyWindow(window);
4215 return;
4218 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
4219 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
4220 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
4221 ok(!!texture, "Got unexpected texture %p.\n", texture);
4223 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
4224 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
4225 ok(!!volume, "Got unexpected volume %p.\n", volume);
4227 /* These should work... */
4228 container = NULL;
4229 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
4230 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4231 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4232 IUnknown_Release(container);
4234 container = NULL;
4235 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
4236 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4237 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4238 IUnknown_Release(container);
4240 container = NULL;
4241 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
4242 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4243 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4244 IUnknown_Release(container);
4246 container = NULL;
4247 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
4248 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4249 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4250 IUnknown_Release(container);
4252 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
4253 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
4254 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
4255 ok(!container, "Got unexpected container %p.\n", container);
4257 IDirect3DVolume9_Release(volume);
4258 IDirect3DVolumeTexture9_Release(texture);
4259 refcount = IDirect3DDevice9_Release(device);
4260 ok(!refcount, "Device has %u references left.\n", refcount);
4261 IDirect3D9_Release(d3d9);
4262 DestroyWindow(window);
4265 static void test_volume_resource(void)
4267 IDirect3DVolumeTexture9 *texture;
4268 IDirect3DResource9 *resource;
4269 IDirect3DVolume9 *volume;
4270 IDirect3DDevice9 *device;
4271 IDirect3D9 *d3d9;
4272 ULONG refcount;
4273 D3DCAPS9 caps;
4274 HWND window;
4275 HRESULT hr;
4277 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4278 0, 0, 640, 480, 0, 0, 0, 0);
4279 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4280 ok(!!d3d9, "Failed to create a D3D object.\n");
4281 if (!(device = create_device(d3d9, window, window, TRUE)))
4283 skip("Failed to create a D3D device, skipping tests.\n");
4284 IDirect3D9_Release(d3d9);
4285 DestroyWindow(window);
4286 return;
4289 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4290 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4291 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
4293 skip("No volume texture support, skipping tests.\n");
4294 IDirect3DDevice9_Release(device);
4295 IDirect3D9_Release(d3d9);
4296 DestroyWindow(window);
4297 return;
4300 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
4301 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
4302 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
4303 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
4304 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
4305 IDirect3DVolumeTexture9_Release(texture);
4307 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
4308 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
4310 IDirect3DVolume9_Release(volume);
4311 refcount = IDirect3DDevice9_Release(device);
4312 ok(!refcount, "Device has %u references left.\n", refcount);
4313 IDirect3D9_Release(d3d9);
4314 DestroyWindow(window);
4317 static void test_vb_lock_flags(void)
4319 static const struct
4321 DWORD flags;
4322 const char *debug_string;
4323 HRESULT win7_result;
4325 test_data[] =
4327 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
4328 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
4329 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
4330 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
4331 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
4332 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
4333 /* Completely bogus flags aren't an error. */
4334 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
4336 IDirect3DVertexBuffer9 *buffer;
4337 IDirect3DDevice9 *device;
4338 IDirect3D9 *d3d9;
4339 unsigned int i;
4340 ULONG refcount;
4341 HWND window;
4342 HRESULT hr;
4343 void *data;
4345 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4346 0, 0, 640, 480, 0, 0, 0, 0);
4347 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4348 ok(!!d3d9, "Failed to create a D3D object.\n");
4349 if (!(device = create_device(d3d9, window, window, TRUE)))
4351 skip("Failed to create a D3D device, skipping tests.\n");
4352 IDirect3D9_Release(d3d9);
4353 DestroyWindow(window);
4354 return;
4357 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
4358 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
4360 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
4362 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
4363 /* Windows XP always returns D3D_OK even with flags that don't make
4364 * sense. Windows 7 returns an error. At least one game (Shaiya)
4365 * depends on the Windows XP result, so mark the Windows 7 behavior as
4366 * broken. */
4367 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
4368 hr, test_data[i].debug_string);
4369 if (SUCCEEDED(hr))
4371 ok(!!data, "Got unexpected data %p.\n", data);
4372 hr = IDirect3DVertexBuffer9_Unlock(buffer);
4373 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4377 IDirect3DVertexBuffer9_Release(buffer);
4378 refcount = IDirect3DDevice9_Release(device);
4379 ok(!refcount, "Device has %u references left.\n", refcount);
4380 IDirect3D9_Release(d3d9);
4381 DestroyWindow(window);
4384 static const char *debug_d3dpool(D3DPOOL pool)
4386 switch (pool)
4388 case D3DPOOL_DEFAULT:
4389 return "D3DPOOL_DEFAULT";
4390 case D3DPOOL_SYSTEMMEM:
4391 return "D3DPOOL_SYSTEMMEM";
4392 case D3DPOOL_SCRATCH:
4393 return "D3DPOOL_SCRATCH";
4394 case D3DPOOL_MANAGED:
4395 return "D3DPOOL_MANAGED";
4396 default:
4397 return "unknown pool";
4401 static void test_vertex_buffer_alignment(void)
4403 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
4404 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
4405 IDirect3DVertexBuffer9 *buffer = NULL;
4406 const unsigned int align = 16;
4407 IDirect3DDevice9 *device;
4408 unsigned int i, j;
4409 IDirect3D9 *d3d9;
4410 ULONG refcount;
4411 HWND window;
4412 HRESULT hr;
4413 void *data;
4415 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4416 0, 0, 640, 480, 0, 0, 0, 0);
4417 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4418 ok(!!d3d9, "Failed to create a D3D object.\n");
4419 if (!(device = create_device(d3d9, window, window, TRUE)))
4421 skip("Failed to create a D3D device, skipping tests.\n");
4422 IDirect3D9_Release(d3d9);
4423 DestroyWindow(window);
4424 return;
4427 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
4429 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
4431 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
4432 if (pools[j] == D3DPOOL_SCRATCH)
4433 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
4434 else
4435 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
4436 debug_d3dpool(pools[j]), sizes[i], hr);
4437 if (FAILED(hr))
4438 continue;
4440 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
4441 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
4442 ok(!((DWORD_PTR)data & (align - 1)),
4443 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
4444 data, align, sizes[i], debug_d3dpool(pools[j]));
4445 hr = IDirect3DVertexBuffer9_Unlock(buffer);
4446 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4447 IDirect3DVertexBuffer9_Release(buffer);
4451 refcount = IDirect3DDevice9_Release(device);
4452 ok(!refcount, "Device has %u references left.\n", refcount);
4453 IDirect3D9_Release(d3d9);
4454 DestroyWindow(window);
4457 static void test_query_support(void)
4459 static const D3DQUERYTYPE queries[] =
4461 D3DQUERYTYPE_VCACHE,
4462 D3DQUERYTYPE_RESOURCEMANAGER,
4463 D3DQUERYTYPE_VERTEXSTATS,
4464 D3DQUERYTYPE_EVENT,
4465 D3DQUERYTYPE_OCCLUSION,
4466 D3DQUERYTYPE_TIMESTAMP,
4467 D3DQUERYTYPE_TIMESTAMPDISJOINT,
4468 D3DQUERYTYPE_TIMESTAMPFREQ,
4469 D3DQUERYTYPE_PIPELINETIMINGS,
4470 D3DQUERYTYPE_INTERFACETIMINGS,
4471 D3DQUERYTYPE_VERTEXTIMINGS,
4472 D3DQUERYTYPE_PIXELTIMINGS,
4473 D3DQUERYTYPE_BANDWIDTHTIMINGS,
4474 D3DQUERYTYPE_CACHEUTILIZATION,
4476 IDirect3DQuery9 *query = NULL;
4477 IDirect3DDevice9 *device;
4478 IDirect3D9 *d3d9;
4479 unsigned int i;
4480 ULONG refcount;
4481 BOOL supported;
4482 HWND window;
4483 HRESULT hr;
4485 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4486 0, 0, 640, 480, 0, 0, 0, 0);
4487 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4488 ok(!!d3d9, "Failed to create a D3D object.\n");
4489 if (!(device = create_device(d3d9, window, window, TRUE)))
4491 skip("Failed to create a D3D device, skipping tests.\n");
4492 IDirect3D9_Release(d3d9);
4493 DestroyWindow(window);
4494 return;
4497 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
4499 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
4500 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4502 supported = hr == D3D_OK;
4504 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
4505 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4507 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
4508 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
4510 if (query)
4512 IDirect3DQuery9_Release(query);
4513 query = NULL;
4517 refcount = IDirect3DDevice9_Release(device);
4518 ok(!refcount, "Device has %u references left.\n", refcount);
4519 IDirect3D9_Release(d3d9);
4520 DestroyWindow(window);
4523 static void test_occlusion_query_states(void)
4525 static const float quad[] =
4527 -1.0f, -1.0f, 0.0f,
4528 -1.0f, 1.0f, 0.0f,
4529 1.0f, 1.0f, 0.0f,
4530 1.0f, -1.0f, 0.0f,
4532 IDirect3DQuery9 *query = NULL;
4533 unsigned int data_size, i;
4534 IDirect3DDevice9 *device;
4535 IDirect3D9 *d3d9;
4536 ULONG refcount;
4537 HWND window;
4538 HRESULT hr;
4539 union
4541 WORD word[4];
4542 DWORD dword[2];
4543 } data;
4544 BOOL broken_occlusion = FALSE;
4545 DWORD expected = screen_width * screen_height;
4547 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4548 0, 0, 640, 480, 0, 0, 0, 0);
4549 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4550 ok(!!d3d9, "Failed to create a D3D object.\n");
4551 if (!(device = create_device(d3d9, window, window, FALSE)))
4553 skip("Failed to create a D3D device, skipping tests.\n");
4554 IDirect3D9_Release(d3d9);
4555 DestroyWindow(window);
4556 return;
4559 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
4560 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
4561 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
4562 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4563 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4564 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
4566 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
4567 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
4568 if (!query)
4570 skip("Occlusion queries are not supported, skipping tests.\n");
4571 IDirect3DDevice9_Release(device);
4572 IDirect3D9_Release(d3d9);
4573 DestroyWindow(window);
4574 return;
4577 data_size = IDirect3DQuery9_GetDataSize(query);
4578 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
4580 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4581 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4582 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
4583 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4585 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4586 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4587 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4588 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4589 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4590 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4592 data.dword[0] = 0x12345678;
4593 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4594 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4595 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
4596 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4597 if (hr == D3D_OK)
4598 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
4600 hr = IDirect3DDevice9_BeginScene(device);
4601 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4602 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
4603 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4604 hr = IDirect3DDevice9_EndScene(device);
4605 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4607 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4608 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4609 for (i = 0; i < 500; ++i)
4611 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4612 break;
4613 Sleep(10);
4615 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4617 memset(&data, 0xff, sizeof(data));
4618 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
4619 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4620 ok(data.dword[0] == expected || broken(!data.dword[0]),
4621 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
4622 if (!data.dword[0])
4624 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
4625 broken_occlusion = TRUE;
4628 memset(&data, 0xff, sizeof(data));
4629 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
4630 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4631 if (!broken_occlusion)
4632 ok(data.word[0] == (WORD)expected,
4633 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
4634 ok(data.word[1] == 0xffff,
4635 "data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
4637 memset(&data, 0xf0, sizeof(data));
4638 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
4639 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4640 if (!broken_occlusion)
4641 ok(data.dword[0] == expected,
4642 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
4643 /* Different drivers seem to return different data in those high bytes on Windows, but they all
4644 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
4645 on AMD and Nvidia respectively). */
4646 if (0)
4648 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
4649 data.dword[1]);
4652 memset(&data, 0xff, sizeof(data));
4653 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
4654 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4655 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
4657 /* This crashes on Windows. */
4658 if (0)
4660 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
4661 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4664 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4665 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4666 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4667 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4668 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4669 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4671 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4673 IDirect3DQuery9_Release(query);
4674 refcount = IDirect3DDevice9_Release(device);
4675 ok(!refcount, "Device has %u references left.\n", refcount);
4676 IDirect3D9_Release(d3d9);
4677 DestroyWindow(window);
4680 static void test_timestamp_query(void)
4682 static const float quad[] =
4684 -1.0f, -1.0f, 0.0f,
4685 -1.0f, 1.0f, 0.0f,
4686 1.0f, 1.0f, 0.0f,
4687 1.0f, -1.0f, 0.0f,
4689 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
4690 unsigned int data_size, i;
4691 IDirect3DDevice9 *device;
4692 IDirect3D9 *d3d9;
4693 ULONG refcount;
4694 HWND window;
4695 HRESULT hr;
4696 DWORD timestamp[2], freq[2];
4697 WORD disjoint[2];
4699 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4700 0, 0, 640, 480, 0, 0, 0, 0);
4701 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4702 ok(!!d3d9, "Failed to create a D3D object.\n");
4703 if (!(device = create_device(d3d9, window, window, TRUE)))
4705 skip("Failed to create a D3D device, skipping tests.\n");
4706 IDirect3D9_Release(d3d9);
4707 DestroyWindow(window);
4708 return;
4711 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
4712 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
4713 if (FAILED(hr))
4715 skip("Timestamp queries are not supported, skipping tests.\n");
4716 IDirect3DDevice9_Release(device);
4717 IDirect3D9_Release(d3d9);
4718 DestroyWindow(window);
4719 return;
4721 data_size = IDirect3DQuery9_GetDataSize(freq_query);
4722 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
4724 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
4725 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4726 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
4727 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
4729 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
4730 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4731 data_size = IDirect3DQuery9_GetDataSize(query);
4732 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
4734 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
4735 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4736 for (i = 0; i < 500; ++i)
4738 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4739 break;
4740 Sleep(10);
4742 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4744 memset(freq, 0xff, sizeof(freq));
4745 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
4746 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4747 ok(freq[1] == 0xffffffff,
4748 "freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
4749 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
4750 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4751 ok(freq[1] != 0xffffffff, "high bytes of freq were not modified (0x%.8x).\n",
4752 freq[1]);
4754 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4755 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4756 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
4757 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4759 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
4760 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4761 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
4762 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4763 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
4764 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4766 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
4767 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4769 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4770 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
4771 hr = IDirect3DDevice9_BeginScene(device);
4772 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4773 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
4774 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4775 hr = IDirect3DDevice9_EndScene(device);
4776 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4778 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4779 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4780 for (i = 0; i < 500; ++i)
4782 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4783 break;
4784 Sleep(10);
4786 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4788 memset(timestamp, 0xff, sizeof(timestamp));
4789 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
4790 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4791 ok(timestamp[1] == 0xffffffff,
4792 "timestamp was modified outside of the expected size (0x%.8x).\n",
4793 timestamp[1]);
4795 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4796 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4797 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4798 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4799 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4800 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4802 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
4803 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4804 for (i = 0; i < 500; ++i)
4806 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4807 break;
4808 Sleep(10);
4810 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4812 memset(disjoint, 0xff, sizeof(disjoint));
4813 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
4814 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4815 ok(disjoint[1] == 0xffff,
4816 "disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
4817 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
4818 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4819 ok(disjoint[1] != 0xffff, "high bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
4821 /* It's not strictly necessary for the TIMESTAMP query to be inside
4822 * a TIMESTAMP_DISJOINT query. */
4823 hr = IDirect3DDevice9_BeginScene(device);
4824 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4825 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
4826 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4827 hr = IDirect3DDevice9_EndScene(device);
4828 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4830 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4831 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4832 for (i = 0; i < 500; ++i)
4834 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4835 break;
4836 Sleep(10);
4838 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4839 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
4840 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4842 IDirect3DQuery9_Release(query);
4843 IDirect3DQuery9_Release(disjoint_query);
4844 IDirect3DQuery9_Release(freq_query);
4845 refcount = IDirect3DDevice9_Release(device);
4846 ok(!refcount, "Device has %u references left.\n", refcount);
4847 IDirect3D9_Release(d3d9);
4848 DestroyWindow(window);
4851 static void test_get_set_vertex_shader(void)
4853 IDirect3DVertexShader9 *current_shader = NULL;
4854 IDirect3DVertexShader9 *shader = NULL;
4855 IDirect3DDevice9 *device;
4856 ULONG refcount, i;
4857 IDirect3D9 *d3d;
4858 D3DCAPS9 caps;
4859 HWND window;
4860 HRESULT hr;
4862 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4863 0, 0, 640, 480, 0, 0, 0, 0);
4864 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4865 ok(!!d3d, "Failed to create a D3D object.\n");
4866 if (!(device = create_device(d3d, window, window, TRUE)))
4868 skip("Failed to create a D3D device, skipping tests.\n");
4869 IDirect3D9_Release(d3d);
4870 DestroyWindow(window);
4871 return;
4874 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4875 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4876 if (!(caps.VertexShaderVersion & 0xffff))
4878 skip("No vertex shader support, skipping tests.\n");
4879 IDirect3DDevice9_Release(device);
4880 IDirect3D9_Release(d3d);
4881 DestroyWindow(window);
4882 return;
4885 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
4886 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4887 ok(!!shader, "Got unexpected shader %p.\n", shader);
4889 /* SetVertexShader() should not touch the shader's refcount. */
4890 i = get_refcount((IUnknown *)shader);
4891 hr = IDirect3DDevice9_SetVertexShader(device, shader);
4892 refcount = get_refcount((IUnknown *)shader);
4893 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
4894 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4896 /* GetVertexShader() should increase the shader's refcount by one. */
4897 i = refcount + 1;
4898 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
4899 refcount = get_refcount((IUnknown *)shader);
4900 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
4901 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4902 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4903 IDirect3DVertexShader9_Release(current_shader);
4905 IDirect3DVertexShader9_Release(shader);
4906 refcount = IDirect3DDevice9_Release(device);
4907 ok(!refcount, "Device has %u references left.\n", refcount);
4908 IDirect3D9_Release(d3d);
4909 DestroyWindow(window);
4912 static void test_vertex_shader_constant(void)
4914 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};
4915 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4916 IDirect3DDevice9 *device;
4917 IDirect3D9 *d3d;
4918 ULONG refcount;
4919 D3DCAPS9 caps;
4920 DWORD consts;
4921 HWND window;
4922 HRESULT hr;
4924 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4925 0, 0, 640, 480, 0, 0, 0, 0);
4926 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4927 ok(!!d3d, "Failed to create a D3D object.\n");
4928 if (!(device = create_device(d3d, window, window, TRUE)))
4930 skip("Failed to create a D3D device, skipping tests.\n");
4931 IDirect3D9_Release(d3d);
4932 DestroyWindow(window);
4933 return;
4936 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4937 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4938 if (!(caps.VertexShaderVersion & 0xffff))
4940 skip("No vertex shader support, skipping tests.\n");
4941 IDirect3DDevice9_Release(device);
4942 IDirect3D9_Release(d3d);
4943 DestroyWindow(window);
4944 return;
4946 consts = caps.MaxVertexShaderConst;
4948 /* A simple check that the stuff works at all. */
4949 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
4950 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4952 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
4953 * consts from MAX - 1. */
4954 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
4955 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4956 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
4957 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4958 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
4959 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4960 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
4961 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4963 /* Constant -1. */
4964 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
4965 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4967 refcount = IDirect3DDevice9_Release(device);
4968 ok(!refcount, "Device has %u references left.\n", refcount);
4969 IDirect3D9_Release(d3d);
4970 DestroyWindow(window);
4973 static void test_get_set_pixel_shader(void)
4975 IDirect3DPixelShader9 *current_shader = NULL;
4976 IDirect3DPixelShader9 *shader = NULL;
4977 IDirect3DDevice9 *device;
4978 ULONG refcount, i;
4979 IDirect3D9 *d3d;
4980 D3DCAPS9 caps;
4981 HWND window;
4982 HRESULT hr;
4984 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4985 0, 0, 640, 480, 0, 0, 0, 0);
4986 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4987 ok(!!d3d, "Failed to create a D3D object.\n");
4988 if (!(device = create_device(d3d, window, window, TRUE)))
4990 skip("Failed to create a D3D device, skipping tests.\n");
4991 IDirect3D9_Release(d3d);
4992 DestroyWindow(window);
4993 return;
4996 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4997 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4998 if (!(caps.PixelShaderVersion & 0xffff))
5000 skip("No pixel shader support, skipping tests.\n");
5001 IDirect3DDevice9_Release(device);
5002 IDirect3D9_Release(d3d);
5003 DestroyWindow(window);
5004 return;
5007 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
5008 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5009 ok(!!shader, "Got unexpected shader %p.\n", shader);
5011 /* SetPixelShader() should not touch the shader's refcount. */
5012 i = get_refcount((IUnknown *)shader);
5013 hr = IDirect3DDevice9_SetPixelShader(device, shader);
5014 refcount = get_refcount((IUnknown *)shader);
5015 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
5016 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5018 /* GetPixelShader() should increase the shader's refcount by one. */
5019 i = refcount + 1;
5020 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
5021 refcount = get_refcount((IUnknown *)shader);
5022 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
5023 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5024 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
5025 IDirect3DPixelShader9_Release(current_shader);
5027 IDirect3DPixelShader9_Release(shader);
5028 refcount = IDirect3DDevice9_Release(device);
5029 ok(!refcount, "Device has %u references left.\n", refcount);
5030 IDirect3D9_Release(d3d);
5031 DestroyWindow(window);
5034 static void test_pixel_shader_constant(void)
5036 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};
5037 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
5038 IDirect3DDevice9 *device;
5039 DWORD consts = 0;
5040 IDirect3D9 *d3d;
5041 ULONG refcount;
5042 D3DCAPS9 caps;
5043 HWND window;
5044 HRESULT hr;
5046 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5047 0, 0, 640, 480, 0, 0, 0, 0);
5048 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5049 ok(!!d3d, "Failed to create a D3D object.\n");
5050 if (!(device = create_device(d3d, window, window, TRUE)))
5052 skip("Failed to create a D3D device, skipping tests.\n");
5053 IDirect3D9_Release(d3d);
5054 DestroyWindow(window);
5055 return;
5058 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5059 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5060 if (!(caps.PixelShaderVersion & 0xffff))
5062 skip("No pixel shader support, skipping tests.\n");
5063 IDirect3DDevice9_Release(device);
5064 IDirect3D9_Release(d3d);
5065 DestroyWindow(window);
5066 return;
5069 /* A simple check that the stuff works at all. */
5070 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
5071 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5073 /* Is there really no max pixel shader constant value??? Test how far I can go. */
5074 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
5075 consts = consts - 1;
5076 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
5078 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
5079 * pointless given the way the constant limit was determined. */
5080 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
5081 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5083 /* Constant -1. */
5084 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
5085 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5087 refcount = IDirect3DDevice9_Release(device);
5088 ok(!refcount, "Device has %u references left.\n", refcount);
5089 IDirect3D9_Release(d3d);
5090 DestroyWindow(window);
5093 static void test_wrong_shader(void)
5095 static const DWORD vs_3_0[] =
5097 0xfffe0300, /* vs_3_0 */
5098 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
5099 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
5100 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
5101 0x0000ffff, /* end */
5104 #if 0
5105 float4 main(const float4 color : COLOR) : SV_TARGET
5107 float4 o;
5109 o = color;
5111 return o;
5113 #endif
5114 static const DWORD ps_4_0[] =
5116 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
5117 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
5118 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
5119 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
5120 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
5121 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
5122 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
5123 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
5124 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
5125 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
5126 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
5127 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
5128 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
5129 0x00000000, 0x00000000, 0x00000000,
5132 IDirect3DVertexShader9 *vs = NULL;
5133 IDirect3DPixelShader9 *ps = NULL;
5134 IDirect3DDevice9 *device;
5135 IDirect3D9 * d3d;
5136 ULONG refcount;
5137 D3DCAPS9 caps;
5138 HWND window;
5139 HRESULT hr;
5141 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5142 0, 0, 640, 480, 0, 0, 0, 0);
5143 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5144 ok(!!d3d, "Failed to create a D3D object.\n");
5145 if (!(device = create_device(d3d, window, window, TRUE)))
5147 skip("Failed to create a D3D device, skipping tests.\n");
5148 IDirect3D9_Release(d3d);
5149 DestroyWindow(window);
5150 return;
5153 /* These should always fail, regardless of supported shader version. */
5154 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
5155 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5156 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
5157 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5158 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
5159 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5161 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5162 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5163 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
5165 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
5166 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5168 else
5169 skip("This GPU supports SM3, skipping unsupported shader test.\n");
5171 refcount = IDirect3DDevice9_Release(device);
5172 ok(!refcount, "Device has %u references left.\n", refcount);
5173 IDirect3D9_Release(d3d);
5174 DestroyWindow(window);
5177 /* Test the default texture stage state values */
5178 static void test_texture_stage_states(void)
5180 IDirect3DDevice9 *device;
5181 IDirect3D9 *d3d;
5182 unsigned int i;
5183 ULONG refcount;
5184 D3DCAPS9 caps;
5185 DWORD value;
5186 HWND window;
5187 HRESULT hr;
5189 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5190 0, 0, 640, 480, 0, 0, 0, 0);
5191 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5192 ok(!!d3d, "Failed to create a D3D object.\n");
5193 if (!(device = create_device(d3d, window, window, TRUE)))
5195 skip("Failed to create a D3D device, skipping tests.\n");
5196 IDirect3D9_Release(d3d);
5197 DestroyWindow(window);
5198 return;
5201 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5202 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5204 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
5206 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
5207 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5208 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
5209 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
5210 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
5211 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5212 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
5213 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
5214 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5215 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
5216 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
5217 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5218 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
5219 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
5220 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
5221 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5222 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
5223 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
5224 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5225 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
5226 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
5227 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5228 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
5229 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
5230 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5231 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
5232 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
5233 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5234 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
5235 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
5236 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5237 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
5238 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
5239 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5240 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
5241 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
5242 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5243 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
5244 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
5245 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5246 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
5247 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
5248 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5249 ok(value == D3DTTFF_DISABLE,
5250 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
5251 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
5252 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5253 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
5254 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
5255 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5256 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
5257 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
5258 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5259 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
5260 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
5261 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
5262 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
5265 refcount = IDirect3DDevice9_Release(device);
5266 ok(!refcount, "Device has %u references left.\n", refcount);
5267 IDirect3D9_Release(d3d);
5268 DestroyWindow(window);
5271 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
5273 IDirect3DCubeTexture9 *texture;
5274 IDirect3D9 *d3d;
5275 HRESULT hr;
5277 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
5278 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
5279 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5280 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
5281 IDirect3D9_Release(d3d);
5282 if (FAILED(hr))
5284 skip("No cube mipmap generation support, skipping tests.\n");
5285 return;
5288 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
5289 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5290 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5291 IDirect3DCubeTexture9_Release(texture);
5293 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
5294 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
5295 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5296 IDirect3DCubeTexture9_Release(texture);
5299 static void test_cube_texture_levels(IDirect3DDevice9 *device)
5301 IDirect3DCubeTexture9 *texture;
5302 IDirect3DSurface9 *surface;
5303 D3DSURFACE_DESC desc;
5304 DWORD levels;
5305 HRESULT hr;
5306 D3DCAPS9 caps;
5308 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5309 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5310 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
5311 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
5313 skip("Failed to create cube texture, skipping tests.\n");
5314 return;
5317 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
5318 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
5319 ok(levels == 7, "Got unexpected levels %u.\n", levels);
5320 else
5321 ok(levels == 1, "Got unexpected levels %u.\n", levels);
5323 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
5324 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5325 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
5326 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5327 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
5328 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5330 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
5331 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5332 IDirect3DSurface9_Release(surface);
5333 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
5334 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5335 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
5336 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5338 IDirect3DCubeTexture9_Release(texture);
5341 static void test_cube_textures(void)
5343 IDirect3DCubeTexture9 *texture;
5344 IDirect3DDevice9 *device;
5345 IDirect3D9 *d3d;
5346 ULONG refcount;
5347 D3DCAPS9 caps;
5348 HWND window;
5349 HRESULT hr;
5351 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5352 0, 0, 640, 480, 0, 0, 0, 0);
5353 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5354 ok(!!d3d, "Failed to create a D3D object.\n");
5355 if (!(device = create_device(d3d, window, window, TRUE)))
5357 skip("Failed to create a D3D device, skipping tests.\n");
5358 IDirect3D9_Release(d3d);
5359 DestroyWindow(window);
5360 return;
5363 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5364 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5366 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
5368 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5369 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
5370 IDirect3DCubeTexture9_Release(texture);
5371 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
5372 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
5373 IDirect3DCubeTexture9_Release(texture);
5374 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
5375 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
5376 IDirect3DCubeTexture9_Release(texture);
5378 else
5380 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5381 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
5382 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
5383 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
5384 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
5385 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
5387 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
5388 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
5389 IDirect3DCubeTexture9_Release(texture);
5391 test_cube_texture_mipmap_gen(device);
5392 test_cube_texture_levels(device);
5394 refcount = IDirect3DDevice9_Release(device);
5395 ok(!refcount, "Device has %u references left.\n", refcount);
5396 IDirect3D9_Release(d3d);
5397 DestroyWindow(window);
5400 static void test_mipmap_gen(void)
5402 D3DTEXTUREFILTERTYPE filter_type;
5403 IDirect3DTexture9 *texture;
5404 IDirect3DSurface9 *surface;
5405 IDirect3DDevice9 *device;
5406 D3DSURFACE_DESC desc;
5407 D3DLOCKED_RECT lr;
5408 IDirect3D9 *d3d;
5409 ULONG refcount;
5410 unsigned int i;
5411 DWORD levels;
5412 HWND window;
5413 HRESULT hr;
5415 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5416 ok(!!d3d, "Failed to create a D3D object.\n");
5418 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5419 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
5421 skip("No mipmap generation support, skipping tests.\n");
5422 IDirect3D9_Release(d3d);
5423 return;
5426 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5427 0, 0, 640, 480, 0, 0, 0, 0);
5428 if (!(device = create_device(d3d, window, window, TRUE)))
5430 skip("Failed to create a D3D device, skipping tests.\n");
5431 IDirect3D9_Release(d3d);
5432 DestroyWindow(window);
5433 return;
5436 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
5437 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5438 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5439 IDirect3DTexture9_Release(texture);
5441 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
5442 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
5443 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5445 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
5446 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
5447 "Got unexpected filter_type %#x.\n", filter_type);
5448 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
5449 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5450 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
5451 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5452 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
5453 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
5454 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
5455 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5457 levels = IDirect3DTexture9_GetLevelCount(texture);
5458 ok(levels == 1, "Got unexpected levels %u.\n", levels);
5460 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
5462 surface = NULL;
5463 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
5464 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
5465 if (surface)
5466 IDirect3DSurface9_Release(surface);
5468 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
5469 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
5471 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
5472 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
5473 if (SUCCEEDED(hr))
5475 hr = IDirect3DTexture9_UnlockRect(texture, i);
5476 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
5479 IDirect3DTexture9_Release(texture);
5481 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
5482 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
5483 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5484 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
5485 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
5486 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5488 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
5489 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
5490 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5491 levels = IDirect3DTexture9_GetLevelCount(texture);
5492 ok(levels == 1, "Got unexpected levels %u.\n", levels);
5493 IDirect3DTexture9_Release(texture);
5495 refcount = IDirect3DDevice9_Release(device);
5496 ok(!refcount, "Device has %u references left.\n", refcount);
5497 IDirect3D9_Release(d3d);
5498 DestroyWindow(window);
5501 static void test_filter(void)
5503 static const struct
5505 DWORD magfilter, minfilter, mipfilter;
5506 BOOL has_texture;
5507 HRESULT result;
5509 tests[] =
5511 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
5512 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
5513 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
5514 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
5515 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
5517 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
5518 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
5519 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
5520 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
5522 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
5523 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
5524 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
5525 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
5526 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
5528 IDirect3DTexture9 *texture;
5529 IDirect3DDevice9 *device;
5530 IDirect3D9 *d3d;
5531 unsigned int i;
5532 ULONG refcount;
5533 DWORD passes;
5534 HWND window;
5535 HRESULT hr;
5537 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5538 ok(!!d3d, "Failed to create a D3D object.\n");
5540 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5541 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
5543 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
5544 IDirect3D9_Release(d3d);
5545 return;
5548 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5549 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
5551 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
5552 IDirect3D9_Release(d3d);
5553 return;
5556 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5557 0, 0, 640, 480, 0, 0, 0, 0);
5558 if (!(device = create_device(d3d, window, window, TRUE)))
5560 skip("Failed to create a D3D device, skipping tests.\n");
5561 IDirect3D9_Release(d3d);
5562 DestroyWindow(window);
5563 return;
5566 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
5567 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
5568 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5570 /* Needed for ValidateDevice(). */
5571 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
5572 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
5574 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
5576 if (tests[i].has_texture)
5578 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
5579 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
5581 else
5583 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5584 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
5587 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
5588 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
5589 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
5590 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
5591 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
5592 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
5594 passes = 0xdeadbeef;
5595 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
5596 ok(hr == tests[i].result,
5597 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
5598 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
5599 tests[i].mipfilter, tests[i].has_texture);
5600 if (SUCCEEDED(hr))
5601 ok(!!passes, "Got unexpected passes %#x.\n", passes);
5602 else
5603 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
5606 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5607 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
5608 IDirect3DTexture9_Release(texture);
5610 refcount = IDirect3DDevice9_Release(device);
5611 ok(!refcount, "Device has %u references left.\n", refcount);
5612 IDirect3D9_Release(d3d);
5613 DestroyWindow(window);
5616 static void test_get_texture(void)
5618 IDirect3DBaseTexture9 *texture;
5619 IDirect3DDevice9 *device;
5620 IDirect3D9 *d3d;
5621 ULONG refcount;
5622 HWND window;
5623 HRESULT hr;
5625 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5626 0, 0, 640, 480, 0, 0, 0, 0);
5627 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5628 ok(!!d3d, "Failed to create a D3D object.\n");
5629 if (!(device = create_device(d3d, window, window, TRUE)))
5631 skip("Failed to create a D3D device, skipping tests.\n");
5632 IDirect3D9_Release(d3d);
5633 DestroyWindow(window);
5634 return;
5637 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
5638 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5639 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5640 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
5641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5642 ok(!texture, "Got unexpected texture %p.\n", texture);
5644 refcount = IDirect3DDevice9_Release(device);
5645 ok(!refcount, "Device has %u references left.\n", refcount);
5646 IDirect3D9_Release(d3d);
5647 DestroyWindow(window);
5650 static void test_lod(void)
5652 IDirect3DTexture9 *texture;
5653 IDirect3DDevice9 *device;
5654 IDirect3D9 *d3d;
5655 ULONG refcount;
5656 HWND window;
5657 HRESULT hr;
5658 DWORD ret;
5660 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5661 0, 0, 640, 480, 0, 0, 0, 0);
5662 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5663 ok(!!d3d, "Failed to create a D3D object.\n");
5664 if (!(device = create_device(d3d, window, window, TRUE)))
5666 skip("Failed to create a D3D device, skipping tests.\n");
5667 IDirect3D9_Release(d3d);
5668 DestroyWindow(window);
5669 return;
5672 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
5673 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5674 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5676 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
5677 * return a HRESULT, so it can't return a normal error. Instead, the call
5678 * is simply ignored. */
5679 ret = IDirect3DTexture9_SetLOD(texture, 0);
5680 ok(!ret, "Got unexpected ret %u.\n", ret);
5681 ret = IDirect3DTexture9_SetLOD(texture, 1);
5682 ok(!ret, "Got unexpected ret %u.\n", ret);
5683 ret = IDirect3DTexture9_SetLOD(texture, 2);
5684 ok(!ret, "Got unexpected ret %u.\n", ret);
5685 ret = IDirect3DTexture9_GetLOD(texture);
5686 ok(!ret, "Got unexpected ret %u.\n", ret);
5688 IDirect3DTexture9_Release(texture);
5689 refcount = IDirect3DDevice9_Release(device);
5690 ok(!refcount, "Device has %u references left.\n", refcount);
5691 IDirect3D9_Release(d3d);
5692 DestroyWindow(window);
5695 static void test_surface_get_container(void)
5697 IDirect3DTexture9 *texture = NULL;
5698 IDirect3DSurface9 *surface = NULL;
5699 IDirect3DDevice9 *device;
5700 IUnknown *container;
5701 IDirect3D9 *d3d;
5702 ULONG refcount;
5703 HWND window;
5704 HRESULT hr;
5706 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5707 0, 0, 640, 480, 0, 0, 0, 0);
5708 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5709 ok(!!d3d, "Failed to create a D3D object.\n");
5710 if (!(device = create_device(d3d, window, window, TRUE)))
5712 skip("Failed to create a D3D device, skipping tests.\n");
5713 IDirect3D9_Release(d3d);
5714 DestroyWindow(window);
5715 return;
5718 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
5719 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5720 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5721 ok(!!texture, "Got unexpected texture %p.\n", texture);
5723 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5724 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5725 ok(!!surface, "Got unexpected surface %p.\n", surface);
5727 /* These should work... */
5728 container = NULL;
5729 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
5730 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5731 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5732 IUnknown_Release(container);
5734 container = NULL;
5735 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
5736 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5737 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5738 IUnknown_Release(container);
5740 container = NULL;
5741 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
5742 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5743 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5744 IUnknown_Release(container);
5746 container = NULL;
5747 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
5748 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5749 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5750 IUnknown_Release(container);
5752 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5753 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
5754 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5755 ok(!container, "Got unexpected container %p.\n", container);
5757 IDirect3DSurface9_Release(surface);
5758 IDirect3DTexture9_Release(texture);
5759 refcount = IDirect3DDevice9_Release(device);
5760 ok(!refcount, "Device has %u references left.\n", refcount);
5761 IDirect3D9_Release(d3d);
5762 DestroyWindow(window);
5765 static void test_surface_alignment(void)
5767 IDirect3DSurface9 *surface;
5768 IDirect3DDevice9 *device;
5769 D3DLOCKED_RECT lr;
5770 unsigned int i, j;
5771 IDirect3D9 *d3d;
5772 ULONG refcount;
5773 HWND window;
5774 HRESULT hr;
5776 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5777 0, 0, 640, 480, 0, 0, 0, 0);
5778 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5779 ok(!!d3d, "Failed to create a D3D object.\n");
5780 if (!(device = create_device(d3d, window, window, TRUE)))
5782 skip("Failed to create a D3D device, skipping tests.\n");
5783 IDirect3D9_Release(d3d);
5784 DestroyWindow(window);
5785 return;
5788 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
5789 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
5790 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
5791 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5793 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5794 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5795 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
5796 /* Some applications also depend on the exact pitch, rather than just the
5797 * alignment. */
5798 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
5799 hr = IDirect3DSurface9_UnlockRect(surface);
5800 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5801 IDirect3DSurface9_Release(surface);
5803 for (i = 0; i < 5; ++i)
5805 IDirect3DTexture9 *texture;
5806 unsigned int level_count;
5807 D3DSURFACE_DESC desc;
5808 int expected_pitch;
5810 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
5811 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
5812 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5813 if (FAILED(hr))
5815 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
5816 continue;
5819 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
5820 for (j = 0; j < level_count; ++j)
5822 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
5823 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
5824 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
5825 hr = IDirect3DTexture9_UnlockRect(texture, j);
5826 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
5828 expected_pitch = ((desc.Width + 3) >> 2) << 3;
5829 if (i > 0)
5830 expected_pitch <<= 1;
5831 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
5832 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
5834 IDirect3DTexture9_Release(texture);
5837 refcount = IDirect3DDevice9_Release(device);
5838 ok(!refcount, "Device has %u references left.\n", refcount);
5839 IDirect3D9_Release(d3d);
5840 DestroyWindow(window);
5843 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
5844 * different from regular formats. This test verifies we return the correct
5845 * memory offsets. */
5846 static void test_lockrect_offset(void)
5848 static const struct
5850 D3DFORMAT format;
5851 const char *name;
5852 unsigned int block_width;
5853 unsigned int block_height;
5854 unsigned int block_size;
5856 dxt_formats[] =
5858 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
5859 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
5860 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
5861 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
5862 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
5863 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
5865 unsigned int expected_offset, offset, i;
5866 const RECT rect = {60, 60, 68, 68};
5867 IDirect3DSurface9 *surface;
5868 D3DLOCKED_RECT locked_rect;
5869 IDirect3DDevice9 *device;
5870 int expected_pitch;
5871 IDirect3D9 *d3d;
5872 ULONG refcount;
5873 HWND window;
5874 BYTE *base;
5875 HRESULT hr;
5877 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5878 0, 0, 640, 480, 0, 0, 0, 0);
5879 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5880 ok(!!d3d, "Failed to create a D3D object.\n");
5881 if (!(device = create_device(d3d, window, window, TRUE)))
5883 skip("Failed to create a D3D device, skipping tests.\n");
5884 IDirect3D9_Release(d3d);
5885 DestroyWindow(window);
5886 return;
5889 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
5891 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5892 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
5894 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
5895 continue;
5898 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5899 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
5900 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5902 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5903 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5905 base = locked_rect.pBits;
5906 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
5907 * dxt_formats[i].block_size;
5908 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
5909 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
5911 hr = IDirect3DSurface9_UnlockRect(surface);
5912 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5914 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5915 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5917 offset = (BYTE *)locked_rect.pBits - base;
5918 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
5919 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
5920 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
5921 offset, dxt_formats[i].name, expected_offset);
5923 hr = IDirect3DSurface9_UnlockRect(surface);
5924 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5926 IDirect3DSurface9_Release(surface);
5929 refcount = IDirect3DDevice9_Release(device);
5930 ok(!refcount, "Device has %u references left.\n", refcount);
5931 IDirect3D9_Release(d3d);
5932 DestroyWindow(window);
5935 static void test_lockrect_invalid(void)
5937 static const struct
5939 RECT rect;
5940 HRESULT win7_result;
5942 test_data[] =
5944 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
5945 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
5946 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
5947 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
5948 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
5949 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
5950 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
5951 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
5952 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
5953 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
5954 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
5955 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
5956 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
5958 static const RECT test_rect_2 = {0, 0, 8, 8};
5959 IDirect3DSurface9 *surface = NULL;
5960 D3DLOCKED_RECT locked_rect;
5961 IDirect3DDevice9 *device;
5962 IDirect3D9 *d3d;
5963 unsigned int i;
5964 ULONG refcount;
5965 HWND window;
5966 BYTE *base;
5967 HRESULT hr;
5969 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5970 0, 0, 640, 480, 0, 0, 0, 0);
5971 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5972 ok(!!d3d, "Failed to create a D3D object.\n");
5973 if (!(device = create_device(d3d, window, window, TRUE)))
5975 skip("Failed to create a D3D device, skipping tests.\n");
5976 IDirect3D9_Release(d3d);
5977 DestroyWindow(window);
5978 return;
5981 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5982 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5983 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5984 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5985 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5986 base = locked_rect.pBits;
5987 hr = IDirect3DSurface9_UnlockRect(surface);
5988 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5990 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5992 unsigned int offset, expected_offset;
5993 const RECT *rect = &test_data[i].rect;
5995 locked_rect.pBits = (BYTE *)0xdeadbeef;
5996 locked_rect.Pitch = 0xdeadbeef;
5998 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
5999 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
6000 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
6001 * one broken. */
6002 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
6003 "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
6004 rect->left, rect->top, rect->right, rect->bottom, hr);
6005 if (FAILED(hr))
6006 continue;
6008 offset = (BYTE *)locked_rect.pBits - base;
6009 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
6010 ok(offset == expected_offset,
6011 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
6012 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
6014 hr = IDirect3DSurface9_UnlockRect(surface);
6015 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6018 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
6019 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
6020 locked_rect.pBits = (BYTE *)0xdeadbeef;
6021 locked_rect.Pitch = 1;
6022 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
6023 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6024 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p\n",
6025 locked_rect.pBits);
6026 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d\n", locked_rect.Pitch);
6027 hr = IDirect3DSurface9_UnlockRect(surface);
6028 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6030 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
6031 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
6032 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
6033 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
6034 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
6035 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
6036 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
6037 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
6038 hr, test_rect_2.left, test_rect_2.top, test_rect_2.right, test_rect_2.bottom);
6039 hr = IDirect3DSurface9_UnlockRect(surface);
6040 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6042 IDirect3DSurface9_Release(surface);
6043 refcount = IDirect3DDevice9_Release(device);
6044 ok(!refcount, "Device has %u references left.\n", refcount);
6045 IDirect3D9_Release(d3d);
6046 DestroyWindow(window);
6049 static void test_private_data(void)
6051 ULONG refcount, expected_refcount;
6052 IDirect3DTexture9 *texture;
6053 IDirect3DSurface9 *surface, *surface2;
6054 IDirect3DDevice9 *device;
6055 IDirect3D9 *d3d;
6056 IUnknown *ptr;
6057 HWND window;
6058 HRESULT hr;
6059 DWORD size;
6060 DWORD data[4] = {1, 2, 3, 4};
6061 static const GUID d3d9_private_data_test_guid =
6063 0xfdb37466,
6064 0x428f,
6065 0x4edf,
6066 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
6068 static const GUID d3d9_private_data_test_guid2 =
6070 0x2e5afac2,
6071 0x87b5,
6072 0x4c10,
6073 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
6076 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6077 0, 0, 640, 480, 0, 0, 0, 0);
6078 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6079 ok(!!d3d, "Failed to create a D3D object.\n");
6080 if (!(device = create_device(d3d, window, window, TRUE)))
6082 skip("Failed to create a D3D device, skipping tests.\n");
6083 IDirect3D9_Release(d3d);
6084 DestroyWindow(window);
6085 return;
6088 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
6089 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
6090 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6092 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
6093 device, 0, D3DSPD_IUNKNOWN);
6094 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6095 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
6096 device, 5, D3DSPD_IUNKNOWN);
6097 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6098 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
6099 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
6100 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6102 /* A failing SetPrivateData call does not clear the old data with the same tag. */
6103 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
6104 sizeof(device), D3DSPD_IUNKNOWN);
6105 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6106 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
6107 sizeof(device) * 2, D3DSPD_IUNKNOWN);
6108 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6109 size = sizeof(ptr);
6110 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
6111 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
6112 IUnknown_Release(ptr);
6113 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
6114 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
6116 refcount = get_refcount((IUnknown *)device);
6117 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
6118 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6119 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6120 expected_refcount = refcount + 1;
6121 refcount = get_refcount((IUnknown *)device);
6122 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
6123 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
6124 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6125 expected_refcount = refcount - 1;
6126 refcount = get_refcount((IUnknown *)device);
6127 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
6129 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
6130 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6131 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6132 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
6133 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6134 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6135 refcount = get_refcount((IUnknown *)device);
6136 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
6138 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
6139 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6140 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6141 size = 2 * sizeof(ptr);
6142 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
6143 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6144 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
6145 expected_refcount = refcount + 2;
6146 refcount = get_refcount((IUnknown *)device);
6147 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
6148 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
6149 IUnknown_Release(ptr);
6150 expected_refcount--;
6152 ptr = (IUnknown *)0xdeadbeef;
6153 size = 1;
6154 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
6155 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6156 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
6157 size = 2 * sizeof(ptr);
6158 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
6159 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6160 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
6161 refcount = get_refcount((IUnknown *)device);
6162 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
6163 size = 1;
6164 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
6165 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
6166 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
6167 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6168 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
6169 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6170 size = 0xdeadbabe;
6171 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
6172 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6173 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6174 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
6175 /* GetPrivateData with size = NULL causes an access violation on Windows if the
6176 * requested data exists. */
6178 /* Destroying the surface frees the held reference. */
6179 IDirect3DSurface9_Release(surface);
6180 expected_refcount = refcount - 2;
6181 refcount = get_refcount((IUnknown *)device);
6182 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
6184 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
6185 &texture, NULL);
6186 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6187 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6188 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
6189 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
6190 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
6192 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
6193 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6195 memset(data, 0, sizeof(data));
6196 size = sizeof(data);
6197 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
6198 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6199 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
6200 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
6201 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
6202 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
6204 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
6205 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
6207 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
6208 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6209 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
6210 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6212 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
6213 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
6215 IDirect3DSurface9_Release(surface2);
6216 IDirect3DSurface9_Release(surface);
6217 IDirect3DTexture9_Release(texture);
6219 refcount = IDirect3DDevice9_Release(device);
6220 ok(!refcount, "Device has %u references left.\n", refcount);
6221 IDirect3D9_Release(d3d);
6222 DestroyWindow(window);
6225 static void test_getdc(void)
6227 static const struct
6229 const char *name;
6230 D3DFORMAT format;
6231 BOOL getdc_supported;
6233 testdata[] =
6235 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, TRUE },
6236 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, TRUE },
6237 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, TRUE },
6238 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, TRUE },
6239 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, TRUE },
6240 {"D3DFMT_R8G8B8", D3DFMT_R8G8B8, TRUE },
6241 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, FALSE}, /* Untested, card on windows didn't support it. */
6242 {"D3DFMT_V8U8", D3DFMT_V8U8, FALSE},
6243 {"D3DFMT_Q8W8V8U8", D3DFMT_Q8W8V8U8, FALSE},
6244 {"D3DFMT_A8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
6245 {"D3DFMT_X8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
6246 {"D3DFMT_R3G3B2", D3DFMT_R3G3B2, FALSE},
6247 {"D3DFMT_P8", D3DFMT_P8, FALSE},
6248 {"D3DFMT_L8", D3DFMT_L8, FALSE},
6249 {"D3DFMT_A8L8", D3DFMT_A8L8, FALSE},
6250 {"D3DFMT_DXT1", D3DFMT_DXT1, FALSE},
6251 {"D3DFMT_DXT2", D3DFMT_DXT2, FALSE},
6252 {"D3DFMT_DXT3", D3DFMT_DXT3, FALSE},
6253 {"D3DFMT_DXT4", D3DFMT_DXT4, FALSE},
6254 {"D3DFMT_DXT5", D3DFMT_DXT5, FALSE},
6256 IDirect3DTexture9 *texture;
6257 IDirect3DSurface9 *surface;
6258 IDirect3DDevice9 *device;
6259 IDirect3D9 *d3d;
6260 unsigned int i;
6261 ULONG refcount;
6262 HWND window;
6263 HRESULT hr;
6264 HDC dc;
6266 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6267 0, 0, 640, 480, 0, 0, 0, 0);
6268 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6269 ok(!!d3d, "Failed to create a D3D object.\n");
6270 if (!(device = create_device(d3d, window, window, TRUE)))
6272 skip("Failed to create a D3D device, skipping tests.\n");
6273 IDirect3D9_Release(d3d);
6274 DestroyWindow(window);
6275 return;
6278 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
6280 texture = NULL;
6281 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
6282 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
6283 if (FAILED(hr))
6285 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
6286 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
6287 if (FAILED(hr))
6289 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
6290 continue;
6292 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6293 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
6296 dc = (void *)0x1234;
6297 hr = IDirect3DSurface9_GetDC(surface, &dc);
6298 if (testdata[i].getdc_supported)
6299 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
6300 else
6301 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
6303 if (SUCCEEDED(hr))
6305 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
6306 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
6308 else
6310 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
6313 IDirect3DSurface9_Release(surface);
6314 if (texture)
6315 IDirect3DTexture9_Release(texture);
6318 refcount = IDirect3DDevice9_Release(device);
6319 ok(!refcount, "Device has %u references left.\n", refcount);
6320 IDirect3D9_Release(d3d);
6321 DestroyWindow(window);
6324 static void test_surface_dimensions(void)
6326 IDirect3DSurface9 *surface;
6327 IDirect3DDevice9 *device;
6328 IDirect3D9 *d3d;
6329 ULONG refcount;
6330 HWND window;
6331 HRESULT hr;
6333 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6334 0, 0, 640, 480, 0, 0, 0, 0);
6335 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6336 ok(!!d3d, "Failed to create a D3D object.\n");
6337 if (!(device = create_device(d3d, window, window, TRUE)))
6339 skip("Failed to create a D3D device, skipping tests.\n");
6340 IDirect3D9_Release(d3d);
6341 DestroyWindow(window);
6342 return;
6345 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
6346 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
6347 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6348 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
6349 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
6350 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6352 refcount = IDirect3DDevice9_Release(device);
6353 ok(!refcount, "Device has %u references left.\n", refcount);
6354 IDirect3D9_Release(d3d);
6355 DestroyWindow(window);
6358 static void test_surface_format_null(void)
6360 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
6361 IDirect3DTexture9 *texture;
6362 IDirect3DSurface9 *surface;
6363 IDirect3DSurface9 *rt, *ds;
6364 D3DLOCKED_RECT locked_rect;
6365 IDirect3DDevice9 *device;
6366 D3DSURFACE_DESC desc;
6367 IDirect3D9 *d3d;
6368 ULONG refcount;
6369 HWND window;
6370 HRESULT hr;
6372 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6373 ok(!!d3d, "Failed to create a D3D object.\n");
6375 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6376 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
6377 if (hr != D3D_OK)
6379 skip("No D3DFMT_NULL support, skipping test.\n");
6380 IDirect3D9_Release(d3d);
6381 return;
6384 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6385 0, 0, 640, 480, 0, 0, 0, 0);
6386 if (!(device = create_device(d3d, window, window, TRUE)))
6388 skip("Failed to create a D3D device, skipping tests.\n");
6389 IDirect3D9_Release(d3d);
6390 DestroyWindow(window);
6391 return;
6394 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6395 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
6396 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
6398 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6399 D3DFMT_NULL, D3DFMT_D24S8);
6400 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
6402 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
6403 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
6404 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
6406 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
6407 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
6409 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
6410 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
6412 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
6413 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
6415 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
6416 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
6418 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
6419 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
6421 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
6422 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
6424 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
6425 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
6427 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
6428 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
6430 IDirect3DSurface9_Release(rt);
6431 IDirect3DSurface9_Release(ds);
6433 hr = IDirect3DSurface9_GetDesc(surface, &desc);
6434 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6435 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
6436 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
6438 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
6439 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6440 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
6441 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
6443 hr = IDirect3DSurface9_UnlockRect(surface);
6444 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6446 IDirect3DSurface9_Release(surface);
6448 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
6449 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
6450 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6451 IDirect3DTexture9_Release(texture);
6453 refcount = IDirect3DDevice9_Release(device);
6454 ok(!refcount, "Device has %u references left.\n", refcount);
6455 IDirect3D9_Release(d3d);
6456 DestroyWindow(window);
6459 static void test_surface_double_unlock(void)
6461 static const D3DPOOL pools[] =
6463 D3DPOOL_DEFAULT,
6464 D3DPOOL_SCRATCH,
6465 D3DPOOL_SYSTEMMEM,
6467 IDirect3DSurface9 *surface;
6468 IDirect3DDevice9 *device;
6469 D3DLOCKED_RECT lr;
6470 IDirect3D9 *d3d;
6471 unsigned int i;
6472 ULONG refcount;
6473 HWND window;
6474 HRESULT hr;
6476 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6477 0, 0, 640, 480, 0, 0, 0, 0);
6478 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6479 ok(!!d3d, "Failed to create a D3D object.\n");
6480 if (!(device = create_device(d3d, window, window, TRUE)))
6482 skip("Failed to create a D3D device, skipping tests.\n");
6483 IDirect3D9_Release(d3d);
6484 DestroyWindow(window);
6485 return;
6488 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
6490 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
6491 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
6492 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
6494 hr = IDirect3DSurface9_UnlockRect(surface);
6495 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
6496 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
6497 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
6498 hr = IDirect3DSurface9_UnlockRect(surface);
6499 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
6500 hr = IDirect3DSurface9_UnlockRect(surface);
6501 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
6503 IDirect3DSurface9_Release(surface);
6506 refcount = IDirect3DDevice9_Release(device);
6507 ok(!refcount, "Device has %u references left.\n", refcount);
6508 IDirect3D9_Release(d3d);
6509 DestroyWindow(window);
6512 static void test_surface_blocks(void)
6514 static const struct
6516 D3DFORMAT fmt;
6517 const char *name;
6518 unsigned int block_width;
6519 unsigned int block_height;
6520 BOOL broken;
6521 BOOL create_size_checked, core_fmt;
6523 formats[] =
6525 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
6526 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
6527 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
6528 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
6529 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
6530 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
6531 * which doesn't match the format spec. On newer Nvidia cards
6532 * it has the correct 4x4 block size */
6533 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
6534 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
6535 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
6537 static const struct
6539 D3DPOOL pool;
6540 const char *name;
6541 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
6542 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
6543 BOOL success;
6545 pools[] =
6547 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
6548 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
6549 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
6550 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
6552 static struct
6554 D3DRESOURCETYPE rtype;
6555 const char *type_name;
6556 D3DPOOL pool;
6557 const char *pool_name;
6558 BOOL need_driver_support, need_runtime_support;
6560 create_tests[] =
6562 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6563 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
6564 /* Managed offscreen plain surfaces are not supported */
6565 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6567 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6568 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
6569 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
6570 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6572 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6573 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
6574 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
6575 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6577 IDirect3DTexture9 *texture;
6578 IDirect3DCubeTexture9 *cube_texture;
6579 IDirect3DSurface9 *surface;
6580 D3DLOCKED_RECT locked_rect;
6581 IDirect3DDevice9 *device;
6582 unsigned int i, j, w, h;
6583 BOOL surface_only;
6584 IDirect3D9 *d3d;
6585 ULONG refcount;
6586 HWND window;
6587 HRESULT hr;
6588 RECT rect;
6589 BOOL tex_pow2, cube_pow2;
6590 D3DCAPS9 caps;
6592 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6593 0, 0, 640, 480, 0, 0, 0, 0);
6594 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6595 ok(!!d3d, "Failed to create a D3D object.\n");
6596 if (!(device = create_device(d3d, window, window, TRUE)))
6598 skip("Failed to create a D3D device, skipping tests.\n");
6599 IDirect3D9_Release(d3d);
6600 DestroyWindow(window);
6601 return;
6604 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6605 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6606 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
6607 if (tex_pow2)
6608 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
6609 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6611 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
6613 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
6615 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6616 0, D3DRTYPE_TEXTURE, formats[i].fmt);
6617 tex_support = SUCCEEDED(hr);
6618 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6619 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
6620 cube_support = SUCCEEDED(hr);
6621 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6622 0, D3DRTYPE_SURFACE, formats[i].fmt);
6623 surface_support = SUCCEEDED(hr);
6625 /* Scratch pool in general allows texture creation even if the driver does
6626 * not support the format. If the format is an extension format that is not
6627 * known to the runtime, like ATI2N, some driver support is required for
6628 * this to work.
6630 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
6631 * about ATI2N. I cannot check this because all my Vista+ machines support
6632 * ATI2N in hardware, but none of my WinXP machines do. */
6633 format_known = tex_support || cube_support || surface_support;
6635 for (w = 1; w <= 8; w++)
6637 for (h = 1; h <= 8; h++)
6639 BOOL block_aligned = TRUE;
6640 BOOL size_is_pow2;
6642 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6643 block_aligned = FALSE;
6645 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
6647 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
6649 BOOL support, pow2;
6650 HRESULT expect_hr;
6651 BOOL may_succeed = FALSE;
6652 IUnknown **check_null;
6654 if (!formats[i].core_fmt)
6656 /* AMD warns against creating ATI2N textures smaller than
6657 * the block size because the runtime cannot calculate the
6658 * correct texture size. Generalize this for all extension
6659 * formats. */
6660 if (w < formats[i].block_width || h < formats[i].block_height)
6661 continue;
6664 texture = (IDirect3DTexture9 *)0xdeadbeef;
6665 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
6666 surface = (IDirect3DSurface9 *)0xdeadbeef;
6668 switch (create_tests[j].rtype)
6670 case D3DRTYPE_TEXTURE:
6671 check_null = (IUnknown **)&texture;
6672 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
6673 formats[i].fmt, create_tests[j].pool, &texture, NULL);
6674 support = tex_support;
6675 pow2 = tex_pow2;
6676 break;
6678 case D3DRTYPE_CUBETEXTURE:
6679 if (w != h)
6680 continue;
6681 check_null = (IUnknown **)&cube_texture;
6682 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
6683 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
6684 support = cube_support;
6685 pow2 = cube_pow2;
6686 break;
6688 case D3DRTYPE_SURFACE:
6689 check_null = (IUnknown **)&surface;
6690 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
6691 formats[i].fmt, create_tests[j].pool, &surface, NULL);
6692 support = surface_support;
6693 pow2 = FALSE;
6694 break;
6696 default:
6697 check_null = NULL;
6698 pow2 = FALSE;
6699 support = FALSE;
6700 break;
6703 if (create_tests[j].need_driver_support && !support)
6704 expect_hr = D3DERR_INVALIDCALL;
6705 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
6706 expect_hr = D3DERR_INVALIDCALL;
6707 else if (formats[i].create_size_checked && !block_aligned)
6708 expect_hr = D3DERR_INVALIDCALL;
6709 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6710 expect_hr = D3DERR_INVALIDCALL;
6711 else
6712 expect_hr = D3D_OK;
6714 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6715 * does not support it. Accept scratch creation of extension formats on
6716 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6717 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6718 * support it. */
6719 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
6720 may_succeed = TRUE;
6722 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6723 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
6724 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
6725 if (FAILED(hr))
6726 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
6727 else
6728 IUnknown_Release(*check_null);
6733 surface_only = FALSE;
6734 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6735 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
6736 dynamic_tex_support = SUCCEEDED(hr);
6737 if (!dynamic_tex_support)
6739 if (!surface_support)
6741 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
6742 continue;
6744 surface_only = TRUE;
6747 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
6749 switch (pools[j].pool)
6751 case D3DPOOL_SYSTEMMEM:
6752 case D3DPOOL_MANAGED:
6753 if (surface_only)
6754 continue;
6755 /* Fall through */
6756 case D3DPOOL_DEFAULT:
6757 if (surface_only)
6759 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6760 formats[i].fmt, pools[j].pool, &surface, NULL);
6761 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6763 else
6765 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
6766 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
6767 formats[i].fmt, pools[j].pool, &texture, NULL);
6768 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6769 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6770 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
6771 IDirect3DTexture9_Release(texture);
6773 break;
6775 case D3DPOOL_SCRATCH:
6776 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6777 formats[i].fmt, pools[j].pool, &surface, NULL);
6778 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6779 break;
6781 default:
6782 break;
6785 if (formats[i].block_width > 1)
6787 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
6788 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6789 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6790 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6791 SUCCEEDED(hr) ? "succeeded" : "failed",
6792 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6793 if (SUCCEEDED(hr))
6795 hr = IDirect3DSurface9_UnlockRect(surface);
6796 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6799 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
6800 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6801 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6802 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6803 SUCCEEDED(hr) ? "succeeded" : "failed",
6804 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6805 if (SUCCEEDED(hr))
6807 hr = IDirect3DSurface9_UnlockRect(surface);
6808 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6812 if (formats[i].block_height > 1)
6814 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
6815 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6816 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6817 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6818 SUCCEEDED(hr) ? "succeeded" : "failed",
6819 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6820 if (SUCCEEDED(hr))
6822 hr = IDirect3DSurface9_UnlockRect(surface);
6823 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6826 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
6827 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6828 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6829 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6830 SUCCEEDED(hr) ? "succeeded" : "failed",
6831 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6832 if (SUCCEEDED(hr))
6834 hr = IDirect3DSurface9_UnlockRect(surface);
6835 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6839 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
6840 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6841 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
6842 hr = IDirect3DSurface9_UnlockRect(surface);
6843 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6845 IDirect3DSurface9_Release(surface);
6848 if (!dynamic_tex_support)
6850 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
6851 continue;
6854 if (formats[i].block_width == 1 && formats[i].block_height == 1)
6855 continue;
6856 if (!formats[i].core_fmt)
6857 continue;
6859 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
6860 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
6861 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
6863 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
6864 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6865 hr = IDirect3DTexture9_UnlockRect(texture, 1);
6866 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6868 rect.left = 0;
6869 rect.top = 0;
6870 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
6871 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
6872 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
6873 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6874 hr = IDirect3DTexture9_UnlockRect(texture, 1);
6875 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6877 rect.right = formats[i].block_width;
6878 rect.bottom = formats[i].block_height;
6879 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
6880 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6881 if (SUCCEEDED(hr))
6882 IDirect3DTexture9_UnlockRect(texture, 1);
6884 IDirect3DTexture9_Release(texture);
6887 refcount = IDirect3DDevice9_Release(device);
6888 ok(!refcount, "Device has %u references left.\n", refcount);
6889 IDirect3D9_Release(d3d);
6890 DestroyWindow(window);
6893 static void test_set_palette(void)
6895 IDirect3DDevice9 *device;
6896 IDirect3D9 *d3d9;
6897 UINT refcount;
6898 HWND window;
6899 HRESULT hr;
6900 PALETTEENTRY pal[256];
6901 unsigned int i;
6902 D3DCAPS9 caps;
6904 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6905 0, 0, 640, 480, 0, 0, 0, 0);
6906 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
6907 ok(!!d3d9, "Failed to create a D3D object.\n");
6908 if (!(device = create_device(d3d9, window, window, TRUE)))
6910 skip("Failed to create a D3D device, skipping tests.\n");
6911 DestroyWindow(window);
6912 return;
6915 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6917 pal[i].peRed = i;
6918 pal[i].peGreen = i;
6919 pal[i].peBlue = i;
6920 pal[i].peFlags = 0xff;
6922 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6923 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6925 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6926 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6927 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6929 pal[i].peRed = i;
6930 pal[i].peGreen = i;
6931 pal[i].peBlue = i;
6932 pal[i].peFlags = i;
6934 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
6936 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6937 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6939 else
6941 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6942 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
6945 refcount = IDirect3DDevice9_Release(device);
6946 ok(!refcount, "Device has %u references left.\n", refcount);
6947 IDirect3D9_Release(d3d9);
6948 DestroyWindow(window);
6951 static void test_swvp_buffer(void)
6953 IDirect3DDevice9 *device;
6954 IDirect3D9 *d3d9;
6955 UINT refcount;
6956 HWND window;
6957 HRESULT hr;
6958 unsigned int i;
6959 IDirect3DVertexBuffer9 *buffer;
6960 static const unsigned int bufsize = 1024;
6961 D3DVERTEXBUFFER_DESC desc;
6962 D3DPRESENT_PARAMETERS present_parameters = {0};
6963 struct
6965 float x, y, z;
6966 } *ptr, *ptr2;
6968 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6969 0, 0, 640, 480, 0, 0, 0, 0);
6970 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
6971 ok(!!d3d9, "Failed to create a D3D object.\n");
6973 present_parameters.Windowed = TRUE;
6974 present_parameters.hDeviceWindow = window;
6975 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
6976 present_parameters.BackBufferWidth = screen_width;
6977 present_parameters.BackBufferHeight = screen_height;
6978 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
6979 present_parameters.EnableAutoDepthStencil = FALSE;
6980 if (FAILED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
6981 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
6983 skip("Failed to create a D3D device, skipping tests.\n");
6984 DestroyWindow(window);
6985 IDirect3D9_Release(d3d9);
6986 return;
6989 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
6990 D3DPOOL_DEFAULT, &buffer, NULL);
6991 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6992 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
6993 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6994 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
6995 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
6996 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
6998 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
6999 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
7000 for (i = 0; i < bufsize; i++)
7002 ptr[i].x = i * 1.0f;
7003 ptr[i].y = i * 2.0f;
7004 ptr[i].z = i * 3.0f;
7006 hr = IDirect3DVertexBuffer9_Unlock(buffer);
7007 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
7009 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7010 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
7011 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
7012 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
7013 hr = IDirect3DDevice9_BeginScene(device);
7014 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7015 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
7016 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7017 hr = IDirect3DDevice9_EndScene(device);
7018 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7020 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
7021 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
7022 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
7023 for (i = 0; i < bufsize; i++)
7025 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
7027 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
7028 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
7029 break;
7032 hr = IDirect3DVertexBuffer9_Unlock(buffer);
7033 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
7035 IDirect3DVertexBuffer9_Release(buffer);
7036 refcount = IDirect3DDevice9_Release(device);
7037 ok(!refcount, "Device has %u references left.\n", refcount);
7038 IDirect3D9_Release(d3d9);
7039 DestroyWindow(window);
7042 static void test_npot_textures(void)
7044 IDirect3DDevice9 *device = NULL;
7045 IDirect3D9 *d3d9;
7046 ULONG refcount;
7047 HWND window = NULL;
7048 HRESULT hr;
7049 D3DCAPS9 caps;
7050 IDirect3DTexture9 *texture;
7051 IDirect3DCubeTexture9 *cube_texture;
7052 IDirect3DVolumeTexture9 *volume_texture;
7053 struct
7055 D3DPOOL pool;
7056 const char *pool_name;
7057 HRESULT hr;
7059 pools[] =
7061 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
7062 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
7063 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
7064 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
7066 unsigned int i, levels;
7067 BOOL tex_pow2, cube_pow2, vol_pow2;
7069 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
7070 0, 0, 640, 480, 0, 0, 0, 0);
7071 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7072 ok(!!d3d9, "Failed to create a D3D object.\n");
7073 if (!(device = create_device(d3d9, window, window, TRUE)))
7075 skip("Failed to create a D3D device, skipping tests.\n");
7076 goto done;
7079 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7080 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7081 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
7082 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
7083 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
7084 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
7085 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
7087 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
7089 for (levels = 0; levels <= 2; levels++)
7091 HRESULT expected;
7093 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
7094 pools[i].pool, &texture, NULL);
7095 if (!tex_pow2)
7097 expected = D3D_OK;
7099 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
7101 if (levels == 1)
7102 expected = D3D_OK;
7103 else
7104 expected = pools[i].hr;
7106 else
7108 expected = pools[i].hr;
7110 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
7111 pools[i].pool_name, levels, hr, expected);
7113 if (SUCCEEDED(hr))
7114 IDirect3DTexture9_Release(texture);
7117 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
7118 &cube_texture, NULL);
7119 if (tex_pow2)
7121 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
7122 pools[i].pool_name, hr, pools[i].hr);
7124 else
7126 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
7127 pools[i].pool_name, hr, D3D_OK);
7130 if (SUCCEEDED(hr))
7131 IDirect3DCubeTexture9_Release(cube_texture);
7133 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
7134 &volume_texture, NULL);
7135 if (tex_pow2)
7137 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
7138 pools[i].pool_name, hr, pools[i].hr);
7140 else
7142 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
7143 pools[i].pool_name, hr, D3D_OK);
7146 if (SUCCEEDED(hr))
7147 IDirect3DVolumeTexture9_Release(volume_texture);
7150 done:
7151 if (device)
7153 refcount = IDirect3DDevice9_Release(device);
7154 ok(!refcount, "Device has %u references left.\n", refcount);
7156 IDirect3D9_Release(d3d9);
7157 DestroyWindow(window);
7161 static void test_vidmem_accounting(void)
7163 IDirect3DDevice9 *device;
7164 IDirect3D9 *d3d9;
7165 ULONG refcount;
7166 HWND window;
7167 HRESULT hr = D3D_OK;
7168 IDirect3DTexture9 *textures[20];
7169 unsigned int i;
7170 UINT vidmem_start, vidmem_end, diff;
7172 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
7173 0, 0, 640, 480, 0, 0, 0, 0);
7174 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7175 ok(!!d3d9, "Failed to create a D3D object.\n");
7176 if (!(device = create_device(d3d9, window, window, TRUE)))
7178 skip("Failed to create a D3D device, skipping tests.\n");
7179 IDirect3D9_Release(d3d9);
7180 DestroyWindow(window);
7181 return;
7184 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
7185 memset(textures, 0, sizeof(textures));
7186 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
7188 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
7189 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
7190 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
7191 * E_FAIL is returned on address space or system memory exhaustion */
7192 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
7193 "Failed to create texture, hr %#x.\n", hr);
7195 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
7197 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
7198 diff = vidmem_start - vidmem_end;
7199 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
7200 2 * i, diff / 1024 / 1024);
7202 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
7204 if (textures[i])
7205 IDirect3DTexture9_Release(textures[i]);
7208 refcount = IDirect3DDevice9_Release(device);
7209 ok(!refcount, "Device has %u references left.\n", refcount);
7210 IDirect3D9_Release(d3d9);
7211 DestroyWindow(window);
7214 static void test_volume_locking(void)
7216 IDirect3DDevice9 *device;
7217 IDirect3D9 *d3d9;
7218 HWND window;
7219 HRESULT hr;
7220 IDirect3DVolumeTexture9 *texture;
7221 unsigned int i;
7222 D3DLOCKED_BOX locked_box;
7223 ULONG refcount;
7224 D3DCAPS9 caps;
7225 static const struct
7227 D3DPOOL pool;
7228 DWORD usage;
7229 HRESULT create_hr, lock_hr;
7231 tests[] =
7233 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
7234 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
7235 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
7236 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
7237 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
7238 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
7239 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
7240 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
7243 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
7244 0, 0, 640, 480, 0, 0, 0, 0);
7245 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7246 ok(!!d3d9, "Failed to create a D3D object.\n");
7247 if (!(device = create_device(d3d9, window, window, TRUE)))
7249 skip("Failed to create a D3D device, skipping tests.\n");
7250 IDirect3D9_Release(d3d9);
7251 DestroyWindow(window);
7252 return;
7255 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7256 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7257 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
7259 skip("Volume textures not supported, skipping test.\n");
7260 goto out;
7263 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
7265 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
7266 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
7267 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
7268 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
7269 if (FAILED(hr))
7270 continue;
7272 locked_box.pBits = (void *)0xdeadbeef;
7273 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7274 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
7275 if (SUCCEEDED(hr))
7277 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7278 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7280 else
7282 ok (locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
7284 IDirect3DVolumeTexture9_Release(texture);
7287 out:
7288 refcount = IDirect3DDevice9_Release(device);
7289 ok(!refcount, "Device has %u references left.\n", refcount);
7290 IDirect3D9_Release(d3d9);
7291 DestroyWindow(window);
7294 static void test_update_volumetexture(void)
7296 IDirect3DDevice9 *device;
7297 IDirect3D9 *d3d9;
7298 HWND window;
7299 HRESULT hr;
7300 IDirect3DVolumeTexture9 *src, *dst;
7301 unsigned int i;
7302 D3DLOCKED_BOX locked_box;
7303 ULONG refcount;
7304 D3DCAPS9 caps;
7305 static const struct
7307 D3DPOOL src_pool, dst_pool;
7308 HRESULT hr;
7310 tests[] =
7312 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
7313 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
7314 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
7315 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
7317 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
7318 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
7319 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
7320 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
7322 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
7323 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
7324 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
7325 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
7327 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
7328 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
7329 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
7330 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
7332 static const struct
7334 UINT src_size, dst_size;
7335 UINT src_lvl, dst_lvl;
7336 D3DFORMAT src_fmt, dst_fmt;
7338 tests2[] =
7340 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7341 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7342 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7343 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7344 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7345 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
7346 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
7347 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
7350 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
7351 0, 0, 640, 480, 0, 0, 0, 0);
7352 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7353 ok(!!d3d9, "Failed to create a D3D object.\n");
7354 if (!(device = create_device(d3d9, window, window, TRUE)))
7356 skip("Failed to create a D3D device, skipping tests.\n");
7357 IDirect3D9_Release(d3d9);
7358 DestroyWindow(window);
7359 return;
7362 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7363 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7364 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
7366 skip("Volume textures not supported, skipping test.\n");
7367 goto out;
7370 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
7372 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
7373 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
7375 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
7376 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
7377 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7378 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
7379 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
7380 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7382 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
7383 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7384 *((DWORD *)locked_box.pBits) = 0x11223344;
7385 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
7386 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7388 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
7389 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
7390 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
7392 if (SUCCEEDED(hr))
7394 DWORD content = *((DWORD *)locked_box.pBits);
7395 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
7396 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7397 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
7398 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
7399 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7401 IDirect3DVolumeTexture9_Release(src);
7402 IDirect3DVolumeTexture9_Release(dst);
7405 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
7407 skip("Mipmapped volume maps not supported.\n");
7408 goto out;
7411 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
7413 hr = IDirect3DDevice9_CreateVolumeTexture(device,
7414 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
7415 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
7416 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
7417 hr = IDirect3DDevice9_CreateVolumeTexture(device,
7418 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
7419 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
7420 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
7422 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
7423 if (FAILED(hr))
7424 todo_wine ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
7425 else
7426 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
7428 IDirect3DVolumeTexture9_Release(src);
7429 IDirect3DVolumeTexture9_Release(dst);
7432 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
7433 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
7434 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
7435 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
7436 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
7438 * I'm not adding tests for this behavior until an application needs it. */
7440 out:
7441 refcount = IDirect3DDevice9_Release(device);
7442 ok(!refcount, "Device has %u references left.\n", refcount);
7443 IDirect3D9_Release(d3d9);
7444 DestroyWindow(window);
7447 static void test_create_rt_ds_fail(void)
7449 IDirect3DDevice9 *device;
7450 HWND window;
7451 HRESULT hr;
7452 ULONG refcount;
7453 IDirect3D9 *d3d9;
7454 IDirect3DSurface9 *surface;
7456 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
7457 0, 0, 640, 480, 0, 0, 0, 0);
7458 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7459 ok(!!d3d9, "Failed to create a D3D object.\n");
7460 if (!(device = create_device(d3d9, window, window, TRUE)))
7462 skip("Failed to create a D3D device, skipping tests.\n");
7463 IDirect3D9_Release(d3d9);
7464 DestroyWindow(window);
7465 return;
7468 /* Output pointer == NULL segfaults on Windows. */
7470 surface = (IDirect3DSurface9 *)0xdeadbeef;
7471 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
7472 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
7473 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
7474 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
7475 if (SUCCEEDED(hr))
7476 IDirect3DSurface9_Release(surface);
7478 surface = (IDirect3DSurface9 *)0xdeadbeef;
7479 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
7480 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
7481 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
7482 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
7483 if (SUCCEEDED(hr))
7484 IDirect3DSurface9_Release(surface);
7486 refcount = IDirect3DDevice9_Release(device);
7487 ok(!refcount, "Device has %u references left.\n", refcount);
7488 IDirect3D9_Release(d3d9);
7489 DestroyWindow(window);
7492 static void test_volume_blocks(void)
7494 IDirect3DDevice9 *device;
7495 IDirect3D9 *d3d9;
7496 UINT refcount;
7497 HWND window;
7498 HRESULT hr;
7499 D3DCAPS9 caps;
7500 IDirect3DVolumeTexture9 *texture;
7501 unsigned int w, h, d, i, j;
7502 static const struct
7504 D3DFORMAT fmt;
7505 const char *name;
7506 unsigned int block_width;
7507 unsigned int block_height;
7508 unsigned int block_depth;
7509 unsigned int block_size;
7510 BOOL broken;
7511 BOOL create_size_checked, core_fmt;
7513 formats[] =
7515 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
7516 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
7517 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, FALSE, TRUE, TRUE },
7518 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, FALSE, TRUE, TRUE },
7519 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, FALSE, TRUE, TRUE },
7520 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, FALSE, TRUE, TRUE },
7521 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE, TRUE },
7522 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE, TRUE },
7523 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
7524 * which doesn't match the format spec. On newer Nvidia cards
7525 * it has the correct 4x4 block size */
7526 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, TRUE, FALSE, FALSE},
7527 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, TRUE, FALSE, TRUE },
7528 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, TRUE, FALSE, TRUE },
7530 static const struct
7532 D3DPOOL pool;
7533 const char *name;
7534 BOOL need_driver_support, need_runtime_support;
7536 create_tests[] =
7538 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7539 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7540 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
7541 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
7543 static const struct
7545 unsigned int x, y, z, x2, y2, z2;
7547 offset_tests[] =
7549 {0, 0, 0, 8, 8, 8},
7550 {0, 0, 3, 8, 8, 8},
7551 {0, 4, 0, 8, 8, 8},
7552 {0, 4, 3, 8, 8, 8},
7553 {4, 0, 0, 8, 8, 8},
7554 {4, 0, 3, 8, 8, 8},
7555 {4, 4, 0, 8, 8, 8},
7556 {4, 4, 3, 8, 8, 8},
7558 D3DBOX box;
7559 D3DLOCKED_BOX locked_box;
7560 BYTE *base;
7561 INT expected_row_pitch, expected_slice_pitch;
7562 BOOL support, support_2d;
7563 BOOL pow2;
7564 unsigned int offset, expected_offset;
7566 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
7567 0, 0, 640, 480, 0, 0, 0, 0);
7568 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7569 ok(!!d3d9, "Failed to create a D3D object.\n");
7570 if (!(device = create_device(d3d9, window, window, TRUE)))
7572 skip("Failed to create a D3D device, skipping tests.\n");
7573 IDirect3D9_Release(d3d9);
7574 DestroyWindow(window);
7575 return;
7577 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7578 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7579 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
7581 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
7583 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7584 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
7585 support = SUCCEEDED(hr);
7586 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7587 0, D3DRTYPE_TEXTURE, formats[i].fmt);
7588 support_2d = SUCCEEDED(hr);
7590 /* Test creation restrictions */
7591 for (w = 1; w <= 8; w++)
7593 for (h = 1; h <= 8; h++)
7595 for (d = 1; d <= 8; d++)
7597 HRESULT expect_hr;
7598 BOOL size_is_pow2;
7599 BOOL block_aligned = TRUE;
7601 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
7602 block_aligned = FALSE;
7604 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
7606 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
7608 BOOL may_succeed = FALSE;
7609 BOOL todo = FALSE;
7611 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
7612 expect_hr = D3DERR_INVALIDCALL;
7613 else if (formats[i].create_size_checked && !block_aligned)
7614 expect_hr = D3DERR_INVALIDCALL;
7615 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
7616 expect_hr = D3DERR_INVALIDCALL;
7617 else if (create_tests[j].need_driver_support && !support)
7619 todo = support_2d;
7620 expect_hr = D3DERR_INVALIDCALL;
7622 else
7623 expect_hr = D3D_OK;
7625 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
7626 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
7627 formats[i].fmt, create_tests[j].pool, &texture, NULL);
7629 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
7630 * does not support it. Accept scratch creation of extension formats on
7631 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
7632 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
7633 * support it. */
7634 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
7635 may_succeed = TRUE;
7637 if (todo)
7639 todo_wine ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
7640 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
7641 hr, formats[i].name, create_tests[j].name, w, h, d);
7643 else
7645 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
7646 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
7647 hr, formats[i].name, create_tests[j].name, w, h, d);
7650 if (FAILED(hr))
7651 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
7652 else
7653 IDirect3DVolumeTexture9_Release(texture);
7659 if (!support && !formats[i].core_fmt)
7660 continue;
7662 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
7663 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
7664 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7666 /* Test lockrect offset */
7667 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
7669 unsigned int bytes_per_pixel;
7670 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
7672 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7673 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7675 base = locked_box.pBits;
7676 if (formats[i].broken)
7678 expected_row_pitch = bytes_per_pixel * 24;
7680 else
7682 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
7683 * formats[i].block_size;
7685 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
7686 locked_box.RowPitch, formats[i].name, expected_row_pitch);
7688 if (formats[i].broken)
7690 expected_slice_pitch = expected_row_pitch * 8;
7692 else
7694 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
7695 * expected_row_pitch;
7697 ok(locked_box.SlicePitch == expected_slice_pitch,
7698 "Got unexpected slice pitch %d for format %s, expected %d.\n",
7699 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
7701 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7702 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
7704 box.Left = offset_tests[j].x;
7705 box.Top = offset_tests[j].y;
7706 box.Front = offset_tests[j].z;
7707 box.Right = offset_tests[j].x2;
7708 box.Bottom = offset_tests[j].y2;
7709 box.Back = offset_tests[j].z2;
7710 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7711 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
7713 offset = (BYTE *)locked_box.pBits - base;
7714 if (formats[i].broken)
7716 expected_offset = box.Front * expected_slice_pitch
7717 + box.Top * expected_row_pitch
7718 + box.Left * bytes_per_pixel;
7720 else
7722 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
7723 + (box.Top / formats[i].block_height) * expected_row_pitch
7724 + (box.Left / formats[i].block_width) * formats[i].block_size;
7726 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
7727 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
7729 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7730 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7733 /* Test partial block locks */
7734 box.Front = 0;
7735 box.Back = 1;
7736 if (formats[i].block_width > 1)
7738 box.Left = formats[i].block_width >> 1;
7739 box.Top = 0;
7740 box.Right = formats[i].block_width;
7741 box.Bottom = formats[i].block_height;
7742 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7743 ok(FAILED(hr) || broken(formats[i].broken),
7744 "Partial block lock succeeded, expected failure, format %s.\n",
7745 formats[i].name);
7746 if (SUCCEEDED(hr))
7748 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7749 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7752 box.Left = 0;
7753 box.Top = 0;
7754 box.Right = formats[i].block_width >> 1;
7755 box.Bottom = formats[i].block_height;
7756 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7757 ok(FAILED(hr) || broken(formats[i].broken),
7758 "Partial block lock succeeded, expected failure, format %s.\n",
7759 formats[i].name);
7760 if (SUCCEEDED(hr))
7762 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7763 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7767 if (formats[i].block_height > 1)
7769 box.Left = 0;
7770 box.Top = formats[i].block_height >> 1;
7771 box.Right = formats[i].block_width;
7772 box.Bottom = formats[i].block_height;
7773 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7774 ok(FAILED(hr) || broken(formats[i].broken),
7775 "Partial block lock succeeded, expected failure, format %s.\n",
7776 formats[i].name);
7777 if (SUCCEEDED(hr))
7779 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7780 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7783 box.Left = 0;
7784 box.Top = 0;
7785 box.Right = formats[i].block_width;
7786 box.Bottom = formats[i].block_height >> 1;
7787 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7788 ok(FAILED(hr) || broken(formats[i].broken),
7789 "Partial block lock succeeded, expected failure, format %s.\n",
7790 formats[i].name);
7791 if (SUCCEEDED(hr))
7793 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7794 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7798 /* Test full block lock */
7799 box.Left = 0;
7800 box.Top = 0;
7801 box.Right = formats[i].block_width;
7802 box.Bottom = formats[i].block_height;
7803 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7804 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7805 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7806 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7808 IDirect3DVolumeTexture9_Release(texture);
7810 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
7811 * does not allocate surfaces smaller than the blocksize properly. */
7812 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
7814 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
7815 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
7817 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
7818 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
7819 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7820 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7822 box.Left = box.Top = box.Front = 0;
7823 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
7824 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
7825 box.Back = 1;
7826 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
7827 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
7828 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7829 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7831 box.Right = formats[i].block_width;
7832 box.Bottom = formats[i].block_height;
7833 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
7834 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7835 if (SUCCEEDED(hr))
7836 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7838 IDirect3DVolumeTexture9_Release(texture);
7842 refcount = IDirect3DDevice9_Release(device);
7843 ok(!refcount, "Device has %u references left.\n", refcount);
7844 IDirect3D9_Release(d3d9);
7845 DestroyWindow(window);
7848 static void test_lockbox_invalid(void)
7850 static const struct
7852 D3DBOX box;
7853 HRESULT result;
7855 test_data[] =
7857 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
7858 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
7859 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
7860 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
7861 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
7862 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
7863 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
7864 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
7865 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
7866 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
7867 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
7868 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
7869 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
7870 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
7872 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
7873 IDirect3DVolumeTexture9 *texture = NULL;
7874 D3DLOCKED_BOX locked_box;
7875 IDirect3DDevice9 *device;
7876 IDirect3D9 *d3d;
7877 unsigned int i;
7878 ULONG refcount;
7879 HWND window;
7880 BYTE *base;
7881 HRESULT hr;
7883 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7884 0, 0, 640, 480, 0, 0, 0, 0);
7885 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7886 ok(!!d3d, "Failed to create a D3D object.\n");
7887 if (!(device = create_device(d3d, window, window, TRUE)))
7889 skip("Failed to create a D3D device, skipping tests.\n");
7890 IDirect3D9_Release(d3d);
7891 DestroyWindow(window);
7892 return;
7895 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
7896 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
7897 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7898 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7899 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7900 base = locked_box.pBits;
7901 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7902 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7904 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
7906 unsigned int offset, expected_offset;
7907 const D3DBOX *box = &test_data[i].box;
7909 locked_box.pBits = (BYTE *)0xdeadbeef;
7910 locked_box.RowPitch = 0xdeadbeef;
7911 locked_box.SlicePitch = 0xdeadbeef;
7913 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
7914 /* Unlike surfaces, volumes properly check the box even in Windows XP */
7915 ok(hr == test_data[i].result,
7916 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
7917 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
7918 test_data[i].result);
7919 if (FAILED(hr))
7920 continue;
7922 offset = (BYTE *)locked_box.pBits - base;
7923 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
7924 ok(offset == expected_offset,
7925 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
7926 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
7928 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7929 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7932 /* locked_box = NULL throws an exception on Windows */
7933 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7934 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7935 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7936 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7937 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7938 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7939 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7940 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7942 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7943 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7944 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7945 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7946 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7947 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7948 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7949 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7950 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
7951 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7952 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
7953 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
7954 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7955 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7957 IDirect3DVolumeTexture9_Release(texture);
7958 refcount = IDirect3DDevice9_Release(device);
7959 ok(!refcount, "Device has %u references left.\n", refcount);
7960 IDirect3D9_Release(d3d);
7961 DestroyWindow(window);
7964 static void test_shared_handle(void)
7966 IDirect3DDevice9 *device;
7967 IDirect3D9 *d3d;
7968 ULONG refcount;
7969 HWND window;
7970 HRESULT hr;
7971 /* Native d3d9ex refuses to create a shared texture if the texture pointer
7972 * is not initialized to NULL. Make sure this doesn't cause issues here. */
7973 IDirect3DTexture9 *texture = NULL;
7974 IDirect3DSurface9 *surface = NULL;
7975 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
7976 IDirect3DIndexBuffer9 *index_buffer = NULL;
7977 HANDLE handle = NULL;
7978 void *mem;
7979 D3DCAPS9 caps;
7981 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7982 0, 0, 640, 480, 0, 0, 0, 0);
7983 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7984 ok(!!d3d, "Failed to create a D3D object.\n");
7985 if (!(device = create_device(d3d, window, window, TRUE)))
7987 skip("Failed to create a D3D device, skipping tests.\n");
7988 IDirect3D9_Release(d3d);
7989 DestroyWindow(window);
7990 return;
7993 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7994 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7995 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
7997 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
7998 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
7999 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
8000 D3DPOOL_DEFAULT, &texture, &handle);
8001 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8002 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
8003 D3DPOOL_SYSTEMMEM, &texture, &mem);
8004 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8006 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8007 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
8008 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8009 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8010 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
8011 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8013 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
8014 &vertex_buffer, &handle);
8015 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8016 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
8017 &vertex_buffer, &mem);
8018 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
8020 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
8021 &index_buffer, &handle);
8022 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8023 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
8024 &index_buffer, &mem);
8025 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8027 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
8029 IDirect3DCubeTexture9 *cube_texture = NULL;
8030 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
8031 D3DPOOL_DEFAULT, &cube_texture, &handle);
8032 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8033 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
8034 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
8035 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8038 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
8040 IDirect3DVolumeTexture9 *volume_texture = NULL;
8041 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
8042 D3DPOOL_DEFAULT, &volume_texture, &handle);
8043 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8044 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
8045 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
8046 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8049 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
8050 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
8051 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8053 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
8054 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
8055 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
8057 HeapFree(GetProcessHeap(), 0, mem);
8058 refcount = IDirect3DDevice9_Release(device);
8059 ok(!refcount, "Device has %u references left.\n", refcount);
8060 IDirect3D9_Release(d3d);
8061 DestroyWindow(window);
8064 static void test_pixel_format(void)
8066 HWND hwnd, hwnd2 = NULL;
8067 HDC hdc, hdc2 = NULL;
8068 HMODULE gl = NULL;
8069 int format, test_format;
8070 PIXELFORMATDESCRIPTOR pfd;
8071 IDirect3D9 *d3d9 = NULL;
8072 IDirect3DDevice9 *device = NULL;
8073 HRESULT hr;
8074 static const float point[3] = {0.0, 0.0, 0.0};
8076 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8077 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8078 if (!hwnd)
8080 skip("Failed to create window\n");
8081 return;
8084 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8085 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8087 hdc = GetDC(hwnd);
8088 if (!hdc)
8090 skip("Failed to get DC\n");
8091 goto cleanup;
8094 if (hwnd2)
8095 hdc2 = GetDC(hwnd2);
8097 gl = LoadLibraryA("opengl32.dll");
8098 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
8100 format = GetPixelFormat(hdc);
8101 ok(format == 0, "new window has pixel format %d\n", format);
8103 ZeroMemory(&pfd, sizeof(pfd));
8104 pfd.nSize = sizeof(pfd);
8105 pfd.nVersion = 1;
8106 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
8107 pfd.iPixelType = PFD_TYPE_RGBA;
8108 pfd.iLayerType = PFD_MAIN_PLANE;
8109 format = ChoosePixelFormat(hdc, &pfd);
8110 if (format <= 0)
8112 skip("no pixel format available\n");
8113 goto cleanup;
8116 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
8118 skip("failed to set pixel format\n");
8119 goto cleanup;
8122 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
8124 skip("failed to set pixel format on second window\n");
8125 if (hdc2)
8127 ReleaseDC(hwnd2, hdc2);
8128 hdc2 = NULL;
8132 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8133 ok(!!d3d9, "Failed to create a D3D object.\n");
8135 test_format = GetPixelFormat(hdc);
8136 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8138 if (!(device = create_device(d3d9, hwnd, hwnd, TRUE)))
8140 skip("Failed to create device\n");
8141 goto cleanup;
8144 test_format = GetPixelFormat(hdc);
8145 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8147 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8148 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
8150 test_format = GetPixelFormat(hdc);
8151 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8153 hr = IDirect3DDevice9_BeginScene(device);
8154 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
8156 test_format = GetPixelFormat(hdc);
8157 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8159 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
8160 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8162 test_format = GetPixelFormat(hdc);
8163 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8165 hr = IDirect3DDevice9_EndScene(device);
8166 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
8168 test_format = GetPixelFormat(hdc);
8169 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8171 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8172 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
8174 test_format = GetPixelFormat(hdc);
8175 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8177 if (hdc2)
8179 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
8180 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
8182 test_format = GetPixelFormat(hdc);
8183 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8185 test_format = GetPixelFormat(hdc2);
8186 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8189 cleanup:
8190 if (device)
8192 UINT refcount = IDirect3DDevice9_Release(device);
8193 ok(!refcount, "Device has %u references left.\n", refcount);
8195 if (d3d9) IDirect3D9_Release(d3d9);
8196 if (gl) FreeLibrary(gl);
8197 if (hdc) ReleaseDC(hwnd, hdc);
8198 if (hdc2) ReleaseDC(hwnd2, hdc2);
8199 if (hwnd) DestroyWindow(hwnd);
8200 if (hwnd2) DestroyWindow(hwnd2);
8203 static void test_begin_end_state_block(void)
8205 IDirect3DStateBlock9 *stateblock;
8206 IDirect3DDevice9 *device;
8207 IDirect3D9 *d3d;
8208 ULONG refcount;
8209 HWND window;
8210 HRESULT hr;
8212 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8213 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8214 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8215 ok(!!d3d, "Failed to create a D3D object.\n");
8216 if (!(device = create_device(d3d, window, window, TRUE)))
8218 skip("Failed to create a D3D device, skipping tests.\n");
8219 IDirect3D9_Release(d3d);
8220 DestroyWindow(window);
8221 return;
8224 /* Should succeed. */
8225 hr = IDirect3DDevice9_BeginStateBlock(device);
8226 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
8228 /* Calling BeginStateBlock() while recording should return
8229 * D3DERR_INVALIDCALL. */
8230 hr = IDirect3DDevice9_BeginStateBlock(device);
8231 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8233 /* Should succeed. */
8234 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
8235 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
8236 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
8237 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
8238 "Got unexpected stateblock %p.\n", stateblock);
8239 IDirect3DStateBlock9_Release(stateblock);
8241 /* Calling EndStateBlock() while not recording should return
8242 * D3DERR_INVALIDCALL. stateblock should not be touched. */
8243 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
8244 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
8245 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8246 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
8247 "Got unexpected stateblock %p.\n", stateblock);
8249 refcount = IDirect3DDevice9_Release(device);
8250 ok(!refcount, "Device has %u references left.\n", refcount);
8251 IDirect3D9_Release(d3d);
8252 DestroyWindow(window);
8255 static void test_shader_constant_apply(void)
8257 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
8258 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
8259 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
8260 IDirect3DStateBlock9 *stateblock;
8261 DWORD vs_version, ps_version;
8262 IDirect3DDevice9 *device;
8263 IDirect3D9 *d3d;
8264 ULONG refcount;
8265 D3DCAPS9 caps;
8266 float ret[4];
8267 HWND window;
8268 HRESULT hr;
8270 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8271 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8272 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8273 ok(!!d3d, "Failed to create a D3D object.\n");
8274 if (!(device = create_device(d3d, window, window, TRUE)))
8276 skip("Failed to create a D3D device, skipping tests.\n");
8277 IDirect3D9_Release(d3d);
8278 DestroyWindow(window);
8279 return;
8282 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8283 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8284 vs_version = caps.VertexShaderVersion & 0xffff;
8285 ps_version = caps.PixelShaderVersion & 0xffff;
8287 if (vs_version)
8289 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
8290 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
8291 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
8292 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
8294 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
8295 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
8296 ok(!memcmp(ret, initial, sizeof(initial)),
8297 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8298 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8299 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
8300 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
8301 ok(!memcmp(ret, initial, sizeof(initial)),
8302 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8303 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8305 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
8306 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
8308 if (ps_version)
8310 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
8311 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
8312 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
8313 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
8315 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
8316 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
8317 ok(!memcmp(ret, initial, sizeof(initial)),
8318 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8319 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8320 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
8321 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
8322 ok(!memcmp(ret, initial, sizeof(initial)),
8323 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8324 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8326 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
8327 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
8330 hr = IDirect3DDevice9_BeginStateBlock(device);
8331 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
8333 if (vs_version)
8335 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
8336 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
8338 if (ps_version)
8340 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
8341 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
8344 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
8345 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
8347 if (vs_version)
8349 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
8350 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
8351 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
8352 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8353 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
8354 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
8355 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
8356 ok(!memcmp(ret, initial, sizeof(initial)),
8357 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8358 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8360 if (ps_version)
8362 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
8363 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
8364 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
8365 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8366 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
8367 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
8368 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
8369 ok(!memcmp(ret, initial, sizeof(initial)),
8370 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8371 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8374 /* Apply doesn't overwrite constants that aren't explicitly set on the
8375 * source stateblock. */
8376 hr = IDirect3DStateBlock9_Apply(stateblock);
8377 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
8379 if (vs_version)
8381 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
8382 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
8383 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
8384 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8385 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
8386 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
8387 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
8388 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
8389 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8390 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
8392 if (ps_version)
8394 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
8395 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
8396 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
8397 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8398 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
8399 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
8400 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
8401 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
8402 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8403 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
8406 IDirect3DStateBlock9_Release(stateblock);
8407 refcount = IDirect3DDevice9_Release(device);
8408 ok(!refcount, "Device has %u references left.\n", refcount);
8409 IDirect3D9_Release(d3d);
8410 DestroyWindow(window);
8413 static void test_vdecl_apply(void)
8415 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
8416 IDirect3DStateBlock9 *stateblock;
8417 IDirect3DDevice9 *device;
8418 IDirect3D9 *d3d;
8419 ULONG refcount;
8420 HWND window;
8421 HRESULT hr;
8423 static const D3DVERTEXELEMENT9 decl1[] =
8425 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8426 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
8427 D3DDECL_END(),
8430 static const D3DVERTEXELEMENT9 decl2[] =
8432 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8433 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
8434 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8435 D3DDECL_END(),
8438 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8439 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8440 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8441 ok(!!d3d, "Failed to create a D3D object.\n");
8442 if (!(device = create_device(d3d, window, window, TRUE)))
8444 skip("Failed to create a D3D device, skipping tests.\n");
8445 IDirect3D9_Release(d3d);
8446 DestroyWindow(window);
8447 return;
8450 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
8451 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
8453 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
8454 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
8456 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8457 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8458 hr = IDirect3DDevice9_BeginStateBlock(device);
8459 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
8460 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
8461 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8462 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
8463 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
8464 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8465 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8466 hr = IDirect3DStateBlock9_Apply(stateblock);
8467 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8468 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8469 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8470 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
8471 declaration, declaration1);
8472 IDirect3DVertexDeclaration9_Release(declaration);
8474 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8475 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8476 hr = IDirect3DStateBlock9_Capture(stateblock);
8477 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8478 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
8479 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8480 hr = IDirect3DStateBlock9_Apply(stateblock);
8481 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8482 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8483 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8484 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
8485 declaration, declaration2);
8486 IDirect3DVertexDeclaration9_Release(declaration);
8488 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
8489 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8490 hr = IDirect3DStateBlock9_Capture(stateblock);
8491 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8492 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8493 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8494 hr = IDirect3DStateBlock9_Apply(stateblock);
8495 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8496 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8497 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8498 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
8499 declaration, declaration2);
8500 IDirect3DVertexDeclaration9_Release(declaration);
8502 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8503 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8504 hr = IDirect3DStateBlock9_Capture(stateblock);
8505 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8506 hr = IDirect3DStateBlock9_Apply(stateblock);
8507 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8508 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8509 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8510 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
8512 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
8513 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8514 hr = IDirect3DStateBlock9_Capture(stateblock);
8515 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8516 hr = IDirect3DStateBlock9_Apply(stateblock);
8517 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8518 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8519 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8520 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
8521 declaration, declaration2);
8522 IDirect3DVertexDeclaration9_Release(declaration);
8524 IDirect3DStateBlock9_Release(stateblock);
8525 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
8526 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8527 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
8528 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
8529 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8530 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8531 hr = IDirect3DStateBlock9_Apply(stateblock);
8532 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8533 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8534 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8535 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
8536 declaration, declaration1);
8537 IDirect3DVertexDeclaration9_Release(declaration);
8539 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8540 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8541 hr = IDirect3DStateBlock9_Capture(stateblock);
8542 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8543 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
8544 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8545 hr = IDirect3DStateBlock9_Apply(stateblock);
8546 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8547 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8548 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8549 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
8550 declaration, declaration2);
8551 IDirect3DVertexDeclaration9_Release(declaration);
8553 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
8554 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8555 hr = IDirect3DStateBlock9_Capture(stateblock);
8556 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8557 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8558 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8559 hr = IDirect3DStateBlock9_Apply(stateblock);
8560 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8561 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8562 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8563 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
8564 declaration, declaration2);
8565 IDirect3DVertexDeclaration9_Release(declaration);
8567 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8568 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8569 hr = IDirect3DStateBlock9_Capture(stateblock);
8570 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8571 hr = IDirect3DStateBlock9_Apply(stateblock);
8572 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8573 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8574 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8575 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
8577 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
8578 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8579 hr = IDirect3DStateBlock9_Capture(stateblock);
8580 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
8581 hr = IDirect3DStateBlock9_Apply(stateblock);
8582 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
8583 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
8584 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
8585 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
8586 declaration, declaration2);
8587 IDirect3DVertexDeclaration9_Release(declaration);
8589 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8590 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
8591 IDirect3DVertexDeclaration9_Release(declaration1);
8592 IDirect3DVertexDeclaration9_Release(declaration2);
8593 IDirect3DStateBlock9_Release(stateblock);
8594 refcount = IDirect3DDevice9_Release(device);
8595 ok(!refcount, "Device has %u references left.\n", refcount);
8596 IDirect3D9_Release(d3d);
8597 DestroyWindow(window);
8600 static void test_resource_type(void)
8602 IDirect3DDevice9 *device;
8603 IDirect3DSurface9 *surface;
8604 IDirect3DTexture9 *texture;
8605 IDirect3DCubeTexture9 *cube_texture;
8606 IDirect3DVolume9 *volume;
8607 IDirect3DVolumeTexture9 *volume_texture;
8608 D3DSURFACE_DESC surface_desc;
8609 D3DVOLUME_DESC volume_desc;
8610 D3DRESOURCETYPE type;
8611 IDirect3D9 *d3d;
8612 ULONG refcount;
8613 HWND window;
8614 HRESULT hr;
8616 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8617 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8618 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8619 ok(!!d3d, "Failed to create a D3D object.\n");
8620 if (!(device = create_device(d3d, window, window, TRUE)))
8622 skip("Failed to create a D3D device, skipping tests.\n");
8623 IDirect3D9_Release(d3d);
8624 DestroyWindow(window);
8625 return;
8628 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
8629 D3DPOOL_SYSTEMMEM, &surface, NULL);
8630 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8631 type = IDirect3DSurface9_GetType(surface);
8632 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
8633 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
8634 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
8635 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8636 surface_desc.Type);
8637 IDirect3DSurface9_Release(surface);
8639 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
8640 D3DPOOL_SYSTEMMEM, &texture, NULL);
8641 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8642 type = IDirect3DTexture9_GetType(texture);
8643 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
8645 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8646 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8647 /* The following code crashes, for the sake of completeness:
8648 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
8649 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
8651 * So applications will not depend on getting the "right" resource type - whatever it
8652 * may be - from the "wrong" vtable. */
8653 type = IDirect3DSurface9_GetType(surface);
8654 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
8655 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
8656 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
8657 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8658 surface_desc.Type);
8659 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
8660 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
8661 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
8662 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
8663 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8664 surface_desc.Type);
8665 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
8666 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
8667 IDirect3DSurface9_Release(surface);
8669 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
8670 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8671 type = IDirect3DSurface9_GetType(surface);
8672 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
8673 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
8674 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
8675 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8676 surface_desc.Type);
8677 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
8678 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
8679 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
8680 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
8681 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8682 surface_desc.Type);
8683 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
8684 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
8685 IDirect3DSurface9_Release(surface);
8686 IDirect3DTexture9_Release(texture);
8688 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
8689 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
8690 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
8691 type = IDirect3DCubeTexture9_GetType(cube_texture);
8692 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
8694 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
8695 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
8696 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
8697 type = IDirect3DSurface9_GetType(surface);
8698 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
8699 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
8700 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
8701 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8702 surface_desc.Type);
8703 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
8704 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
8705 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8706 surface_desc.Type);
8707 IDirect3DSurface9_Release(surface);
8708 IDirect3DCubeTexture9_Release(cube_texture);
8710 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
8711 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
8712 type = IDirect3DVolumeTexture9_GetType(volume_texture);
8713 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
8715 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
8716 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
8717 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
8718 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
8719 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
8720 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8721 volume_desc.Type);
8722 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
8723 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
8724 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
8725 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
8726 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
8727 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8728 volume_desc.Type);
8729 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
8730 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
8731 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
8732 IDirect3DVolume9_Release(volume);
8734 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
8735 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
8736 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
8737 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
8738 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
8739 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8740 volume_desc.Type);
8741 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
8742 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
8743 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
8744 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
8745 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
8746 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8747 volume_desc.Type);
8748 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
8749 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
8750 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
8751 IDirect3DVolume9_Release(volume);
8752 IDirect3DVolumeTexture9_Release(volume_texture);
8754 refcount = IDirect3DDevice9_Release(device);
8755 ok(!refcount, "Device has %u references left.\n", refcount);
8756 IDirect3D9_Release(d3d);
8757 DestroyWindow(window);
8760 static void test_mipmap_lock(void)
8762 IDirect3DDevice9 *device;
8763 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
8764 IDirect3DTexture9 *texture, *texture_dst;
8765 IDirect3D9 *d3d;
8766 ULONG refcount;
8767 HWND window;
8768 HRESULT hr;
8769 D3DLOCKED_RECT locked_rect;
8771 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8772 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8773 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8774 ok(!!d3d, "Failed to create a D3D object.\n");
8775 if (!(device = create_device(d3d, window, window, TRUE)))
8777 skip("Failed to create a D3D device, skipping tests.\n");
8778 IDirect3D9_Release(d3d);
8779 DestroyWindow(window);
8780 return;
8783 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
8784 D3DPOOL_DEFAULT, &texture_dst, NULL);
8785 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8786 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
8787 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8788 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
8789 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8791 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
8792 D3DPOOL_SYSTEMMEM, &texture, NULL);
8793 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8794 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8795 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8796 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
8797 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8799 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8800 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8801 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
8802 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8803 hr = IDirect3DSurface9_UnlockRect(surface);
8804 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8806 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
8807 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
8808 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
8809 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8811 /* Apparently there's no validation on the container. */
8812 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
8813 (IDirect3DBaseTexture9 *)texture_dst);
8814 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
8816 hr = IDirect3DSurface9_UnlockRect(surface2);
8817 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8819 IDirect3DSurface9_Release(surface_dst2);
8820 IDirect3DSurface9_Release(surface_dst);
8821 IDirect3DSurface9_Release(surface2);
8822 IDirect3DSurface9_Release(surface);
8823 IDirect3DTexture9_Release(texture_dst);
8824 IDirect3DTexture9_Release(texture);
8826 refcount = IDirect3DDevice9_Release(device);
8827 ok(!refcount, "Device has %u references left.\n", refcount);
8828 IDirect3D9_Release(d3d);
8829 DestroyWindow(window);
8832 static void test_writeonly_resource(void)
8834 IDirect3D9 *d3d;
8835 IDirect3DDevice9 *device;
8836 IDirect3DVertexBuffer9 *buffer;
8837 ULONG refcount;
8838 HWND window;
8839 HRESULT hr;
8840 void *ptr;
8841 static const struct
8843 struct vec3 pos;
8845 quad[] =
8847 {{-1.0f, -1.0f, 0.0f}},
8848 {{-1.0f, 1.0f, 0.0f}},
8849 {{ 1.0f, -1.0f, 0.0f}},
8850 {{ 1.0f, 1.0f, 0.0f}}
8853 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8854 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8855 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8856 ok(!!d3d, "Failed to create a D3D object.\n");
8857 if (!(device = create_device(d3d, window, window, TRUE)))
8859 skip("Failed to create a D3D device, skipping tests.\n");
8860 IDirect3D9_Release(d3d);
8861 DestroyWindow(window);
8862 return;
8865 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
8866 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
8867 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8869 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
8870 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8871 memcpy(ptr, quad, sizeof(quad));
8872 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8873 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8874 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
8875 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8876 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8877 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
8879 hr = IDirect3DDevice9_BeginScene(device);
8880 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
8881 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
8882 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8883 hr = IDirect3DDevice9_EndScene(device);
8884 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
8886 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
8887 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8888 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8889 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8890 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8892 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
8893 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8894 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8895 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8896 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8898 refcount = IDirect3DVertexBuffer9_Release(buffer);
8899 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
8900 refcount = IDirect3DDevice9_Release(device);
8901 ok(!refcount, "Device has %u references left.\n", refcount);
8902 IDirect3D9_Release(d3d);
8903 DestroyWindow(window);
8906 static void test_lost_device(void)
8908 IDirect3DDevice9 *device;
8909 IDirect3D9 *d3d;
8910 ULONG refcount;
8911 HWND window;
8912 HRESULT hr;
8913 BOOL ret;
8915 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8916 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8917 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8918 ok(!!d3d, "Failed to create a D3D object.\n");
8919 if (!(device = create_device(d3d, window, window, FALSE)))
8921 skip("Failed to create a D3D device, skipping tests.\n");
8922 goto done;
8925 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8926 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8927 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8928 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8930 ret = SetForegroundWindow(GetDesktopWindow());
8931 ok(ret, "Failed to set foreground window.\n");
8932 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8933 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
8934 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8935 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
8937 ret = ShowWindow(window, SW_RESTORE);
8938 ok(ret, "Failed to restore window.\n");
8939 ret = SetForegroundWindow(window);
8940 ok(ret, "Failed to set foreground window.\n");
8941 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8942 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
8943 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8944 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
8946 hr = reset_device(device, window, FALSE);
8947 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8948 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8949 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8950 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8951 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8953 hr = reset_device(device, window, TRUE);
8954 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8955 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8956 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8957 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8958 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8960 ret = SetForegroundWindow(GetDesktopWindow());
8961 ok(ret, "Failed to set foreground window.\n");
8962 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8963 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8964 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8965 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8967 ret = ShowWindow(window, SW_RESTORE);
8968 ok(ret, "Failed to restore window.\n");
8969 ret = SetForegroundWindow(window);
8970 ok(ret, "Failed to set foreground window.\n");
8971 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8972 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8973 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8974 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8976 hr = reset_device(device, window, FALSE);
8977 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8978 hr = IDirect3DDevice9_TestCooperativeLevel(device);
8979 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8980 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8981 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8983 refcount = IDirect3DDevice9_Release(device);
8984 ok(!refcount, "Device has %u references left.\n", refcount);
8985 done:
8986 IDirect3D9_Release(d3d);
8987 DestroyWindow(window);
8990 START_TEST(device)
8992 WNDCLASSA wc = {0};
8993 IDirect3D9 *d3d9;
8995 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
8997 skip("could not create D3D9 object\n");
8998 return;
9000 IDirect3D9_Release(d3d9);
9002 wc.lpfnWndProc = DefWindowProcA;
9003 wc.lpszClassName = "d3d9_test_wc";
9004 RegisterClassA(&wc);
9006 screen_width = GetSystemMetrics(SM_CXSCREEN);
9007 screen_height = GetSystemMetrics(SM_CYSCREEN);
9009 test_get_set_vertex_declaration();
9010 test_get_declaration();
9011 test_fvf_decl_conversion();
9012 test_fvf_decl_management();
9013 test_vertex_declaration_alignment();
9014 test_unused_declaration_type();
9015 test_fpu_setup();
9016 test_multi_device();
9017 test_display_formats();
9018 test_display_modes();
9019 test_swapchain();
9020 test_refcount();
9021 test_mipmap_levels();
9022 test_checkdevicemultisampletype();
9023 test_cursor();
9024 test_cursor_pos();
9025 test_reset_fullscreen();
9026 test_reset();
9027 test_scene();
9028 test_limits();
9029 test_depthstenciltest();
9030 test_get_rt();
9031 test_draw_indexed();
9032 test_null_stream();
9033 test_lights();
9034 test_set_stream_source();
9035 test_scissor_size();
9036 test_wndproc();
9037 test_wndproc_windowed();
9038 test_window_style();
9039 test_mode_change();
9040 test_device_window_reset();
9041 test_reset_resources();
9042 test_set_rt_vp_scissor();
9043 test_volume_get_container();
9044 test_volume_resource();
9045 test_vb_lock_flags();
9046 test_vertex_buffer_alignment();
9047 test_query_support();
9048 test_occlusion_query_states();
9049 test_timestamp_query();
9050 test_get_set_vertex_shader();
9051 test_vertex_shader_constant();
9052 test_get_set_pixel_shader();
9053 test_pixel_shader_constant();
9054 test_wrong_shader();
9055 test_texture_stage_states();
9056 test_cube_textures();
9057 test_mipmap_gen();
9058 test_filter();
9059 test_get_texture();
9060 test_lod();
9061 test_surface_get_container();
9062 test_surface_alignment();
9063 test_lockrect_offset();
9064 test_lockrect_invalid();
9065 test_private_data();
9066 test_getdc();
9067 test_surface_dimensions();
9068 test_surface_format_null();
9069 test_surface_double_unlock();
9070 test_surface_blocks();
9071 test_set_palette();
9072 test_swvp_buffer();
9073 test_npot_textures();
9074 test_vidmem_accounting();
9075 test_volume_locking();
9076 test_update_volumetexture();
9077 test_create_rt_ds_fail();
9078 test_volume_blocks();
9079 test_lockbox_invalid();
9080 test_shared_handle();
9081 test_pixel_format();
9082 test_begin_end_state_block();
9083 test_shader_constant_apply();
9084 test_vdecl_apply();
9085 test_resource_type();
9086 test_mipmap_lock();
9087 test_writeonly_resource();
9088 test_lost_device();
9090 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));