dxgi: Implement dxgi_swapchain_GetParent().
[wine.git] / dlls / dxgi / tests / device.c
blob5808b6428f370ac49024d585b333aaa1692ec5ad
1 /*
2 * Copyright 2008 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
20 #include "initguid.h"
21 #include "d3d11.h"
22 #include "wine/test.h"
24 enum frame_latency
26 DEFAULT_FRAME_LATENCY = 3,
27 MAX_FRAME_LATENCY = 16,
30 static DEVMODEW registry_mode;
32 static HRESULT (WINAPI *pCreateDXGIFactory1)(REFIID iid, void **factory);
34 static ULONG get_refcount(IUnknown *iface)
36 IUnknown_AddRef(iface);
37 return IUnknown_Release(iface);
40 static IDXGIDevice *create_device(void)
42 IDXGIDevice *dxgi_device;
43 ID3D10Device *device;
44 HRESULT hr;
46 if (SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &device)))
47 goto success;
48 if (SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_WARP, NULL, 0, D3D10_SDK_VERSION, &device)))
49 goto success;
50 if (SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL, 0, D3D10_SDK_VERSION, &device)))
51 goto success;
53 return NULL;
55 success:
56 hr = ID3D10Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
57 ok(SUCCEEDED(hr), "Created device does not implement IDXGIDevice\n");
58 ID3D10Device_Release(device);
60 return dxgi_device;
63 static void test_adapter_desc(void)
65 DXGI_ADAPTER_DESC1 desc1;
66 IDXGIAdapter1 *adapter1;
67 DXGI_ADAPTER_DESC desc;
68 IDXGIAdapter *adapter;
69 IDXGIDevice *device;
70 ULONG refcount;
71 HRESULT hr;
73 if (!(device = create_device()))
75 skip("Failed to create device, skipping tests.\n");
76 return;
79 hr = IDXGIDevice_GetAdapter(device, &adapter);
80 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
82 hr = IDXGIAdapter_GetDesc(adapter, NULL);
83 ok(hr == E_INVALIDARG, "GetDesc returned %#x, expected %#x.\n",
84 hr, E_INVALIDARG);
86 hr = IDXGIAdapter_GetDesc(adapter, &desc);
87 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
89 trace("%s.\n", wine_dbgstr_w(desc.Description));
90 trace("%04x: %04x:%04x (rev %02x).\n",
91 desc.SubSysId, desc.VendorId, desc.DeviceId, desc.Revision);
92 trace("Dedicated video memory: %lu (%lu MB).\n",
93 desc.DedicatedVideoMemory, desc.DedicatedVideoMemory / (1024 * 1024));
94 trace("Dedicated system memory: %lu (%lu MB).\n",
95 desc.DedicatedSystemMemory, desc.DedicatedSystemMemory / (1024 * 1024));
96 trace("Shared system memory: %lu (%lu MB).\n",
97 desc.SharedSystemMemory, desc.SharedSystemMemory / (1024 * 1024));
98 trace("LUID: %08x:%08x.\n", desc.AdapterLuid.HighPart, desc.AdapterLuid.LowPart);
100 hr = IDXGIAdapter_QueryInterface(adapter, &IID_IDXGIAdapter1, (void **)&adapter1);
101 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE), "Got unexpected hr %#x.\n", hr);
102 if (hr == E_NOINTERFACE)
103 goto done;
105 hr = IDXGIAdapter1_GetDesc1(adapter1, &desc1);
106 ok(SUCCEEDED(hr), "GetDesc1 failed, hr %#x.\n", hr);
108 ok(!lstrcmpW(desc.Description, desc1.Description),
109 "Got unexpected description %s.\n", wine_dbgstr_w(desc1.Description));
110 ok(desc1.VendorId == desc.VendorId, "Got unexpected vendor ID %04x.\n", desc1.VendorId);
111 ok(desc1.DeviceId == desc.DeviceId, "Got unexpected device ID %04x.\n", desc1.DeviceId);
112 ok(desc1.SubSysId == desc.SubSysId, "Got unexpected sub system ID %04x.\n", desc1.SubSysId);
113 ok(desc1.Revision == desc.Revision, "Got unexpected revision %02x.\n", desc1.Revision);
114 ok(desc1.DedicatedVideoMemory == desc.DedicatedVideoMemory,
115 "Got unexpected dedicated video memory %lu.\n", desc1.DedicatedVideoMemory);
116 ok(desc1.DedicatedSystemMemory == desc.DedicatedSystemMemory,
117 "Got unexpected dedicated system memory %lu.\n", desc1.DedicatedSystemMemory);
118 ok(desc1.SharedSystemMemory == desc.SharedSystemMemory,
119 "Got unexpected shared system memory %lu.\n", desc1.SharedSystemMemory);
120 ok(!memcmp(&desc.AdapterLuid, &desc1.AdapterLuid, sizeof(desc.AdapterLuid)),
121 "Got unexpected adapter LUID %08x:%08x.\n", desc1.AdapterLuid.HighPart, desc1.AdapterLuid.LowPart);
122 trace("Flags: %08x.\n", desc1.Flags);
124 IDXGIAdapter1_Release(adapter1);
126 done:
127 IDXGIAdapter_Release(adapter);
128 refcount = IDXGIDevice_Release(device);
129 ok(!refcount, "Device has %u references left.\n", refcount);
132 static void test_check_interface_support(void)
134 LARGE_INTEGER driver_version;
135 IDXGIAdapter *adapter;
136 IDXGIDevice *device;
137 IUnknown *iface;
138 ULONG refcount;
139 HRESULT hr;
141 if (!(device = create_device()))
143 skip("Failed to create device.\n");
144 return;
147 hr = IDXGIDevice_GetAdapter(device, &adapter);
148 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
150 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, NULL);
151 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
152 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, &driver_version);
153 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
155 trace("UMD version: %u.%u.%u.%u.\n",
156 HIWORD(U(driver_version).HighPart), LOWORD(U(driver_version).HighPart),
157 HIWORD(U(driver_version).LowPart), LOWORD(U(driver_version).LowPart));
159 hr = IDXGIDevice_QueryInterface(device, &IID_ID3D10Device1, (void **)&iface);
160 if (SUCCEEDED(hr))
162 IUnknown_Release(iface);
163 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, NULL);
164 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
165 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, &driver_version);
166 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
168 else
170 win_skip("D3D10.1 is not supported.\n");
173 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, NULL);
174 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
175 driver_version.HighPart = driver_version.LowPart = 0xdeadbeef;
176 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, &driver_version);
177 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
178 ok(driver_version.HighPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.HighPart);
179 ok(driver_version.LowPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.LowPart);
181 IDXGIAdapter_Release(adapter);
182 refcount = IDXGIDevice_Release(device);
183 ok(!refcount, "Device has %u references left.\n", refcount);
186 static void test_create_surface(void)
188 DXGI_SURFACE_DESC desc;
189 IDXGISurface *surface;
190 IDXGIDevice *device;
191 IUnknown *surface1;
192 IUnknown *texture;
193 ULONG refcount;
194 HRESULT hr;
196 if (!(device = create_device()))
198 skip("Failed to create device, skipping tests.\n");
199 return;
202 desc.Width = 512;
203 desc.Height = 512;
204 desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
205 desc.SampleDesc.Count = 1;
206 desc.SampleDesc.Quality = 0;
208 hr = IDXGIDevice_CreateSurface(device, &desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
209 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
211 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Texture2D, (void **)&texture);
212 ok(SUCCEEDED(hr), "Surface should implement ID3D10Texture2D\n");
213 IUnknown_Release(texture);
215 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture);
216 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
217 "Surface should implement ID3D11Texture2D.\n");
218 if (SUCCEEDED(hr)) IUnknown_Release(texture);
220 hr = IDXGISurface_QueryInterface(surface, &IID_IDXGISurface1, (void **)&surface1);
221 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
222 "Surface should implement IDXGISurface1.\n");
223 if (SUCCEEDED(hr)) IUnknown_Release(surface1);
225 IDXGISurface_Release(surface);
226 refcount = IDXGIDevice_Release(device);
227 ok(!refcount, "Device has %u references left.\n", refcount);
230 static void test_parents(void)
232 DXGI_SURFACE_DESC surface_desc;
233 IDXGISurface *surface;
234 IDXGIFactory *factory;
235 IDXGIAdapter *adapter;
236 IDXGIDevice *device;
237 IDXGIOutput *output;
238 IUnknown *parent;
239 ULONG refcount;
240 HRESULT hr;
242 if (!(device = create_device()))
244 skip("Failed to create device, skipping tests.\n");
245 return;
248 surface_desc.Width = 512;
249 surface_desc.Height = 512;
250 surface_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
251 surface_desc.SampleDesc.Count = 1;
252 surface_desc.SampleDesc.Quality = 0;
254 hr = IDXGIDevice_CreateSurface(device, &surface_desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
255 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
257 hr = IDXGISurface_GetParent(surface, &IID_IDXGIDevice, (void **)&parent);
258 IDXGISurface_Release(surface);
259 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
260 ok(parent == (IUnknown *)device, "Got parent %p, expected %p.\n", parent, device);
261 IUnknown_Release(parent);
263 hr = IDXGIDevice_GetAdapter(device, &adapter);
264 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
266 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
267 if (hr == DXGI_ERROR_NOT_FOUND)
269 skip("Adapter has not outputs, skipping output tests.\n");
271 else
273 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
275 hr = IDXGIOutput_GetParent(output, &IID_IDXGIAdapter, (void **)&parent);
276 IDXGIOutput_Release(output);
277 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
278 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
279 IUnknown_Release(parent);
282 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
283 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
285 hr = IDXGIFactory_GetParent(factory, &IID_IUnknown, (void **)&parent);
286 ok(hr == E_NOINTERFACE, "GetParent returned %#x, expected %#x.\n", hr, E_NOINTERFACE);
287 ok(parent == NULL, "Got parent %p, expected %p.\n", parent, NULL);
288 IDXGIFactory_Release(factory);
290 hr = IDXGIDevice_GetParent(device, &IID_IDXGIAdapter, (void **)&parent);
291 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
292 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
293 IUnknown_Release(parent);
295 IDXGIAdapter_Release(adapter);
296 refcount = IDXGIDevice_Release(device);
297 ok(!refcount, "Device has %u references left.\n", refcount);
300 static void test_output(void)
302 IDXGIAdapter *adapter;
303 IDXGIDevice *device;
304 HRESULT hr;
305 IDXGIOutput *output;
306 ULONG refcount;
307 UINT mode_count, mode_count_comp, i;
308 DXGI_MODE_DESC *modes;
310 if (!(device = create_device()))
312 skip("Failed to create device, skipping tests.\n");
313 return;
316 hr = IDXGIDevice_GetAdapter(device, &adapter);
317 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
319 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
320 if (hr == DXGI_ERROR_NOT_FOUND)
322 skip("Adapter doesn't have any outputs, skipping tests.\n");
323 IDXGIAdapter_Release(adapter);
324 IDXGIDevice_Release(device);
325 return;
327 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
329 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, NULL, NULL);
330 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
332 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
333 ok(SUCCEEDED(hr)
334 || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Remote Desktop Services / Win 7 testbot */
335 "Failed to list modes, hr %#x.\n", hr);
336 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
338 skip("GetDisplayModeList() not supported, skipping tests.\n");
339 IDXGIOutput_Release(output);
340 IDXGIAdapter_Release(adapter);
341 IDXGIDevice_Release(device);
342 return;
344 mode_count_comp = mode_count;
346 hr = IDXGIOutput_GetDisplayModeList(output, 0, 0, &mode_count, NULL);
347 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
348 ok(!mode_count, "Got unexpected mode_count %u.\n", mode_count);
350 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
351 DXGI_ENUM_MODES_SCALING, &mode_count, NULL);
352 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
353 ok(mode_count >= mode_count_comp, "Got unexpected mode_count %u, expected >= %u.\n", mode_count, mode_count_comp);
354 mode_count_comp = mode_count;
356 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * (mode_count + 10));
358 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
359 DXGI_ENUM_MODES_SCALING, NULL, modes);
360 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
361 ok(!modes[0].Height, "No output was expected.\n");
363 mode_count = 0;
364 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
365 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
366 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
367 ok(!modes[0].Height, "No output was expected.\n");
369 mode_count = mode_count_comp;
370 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
371 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
372 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
373 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
375 for (i = 0; i < mode_count; i++)
377 ok(modes[i].Height && modes[i].Width, "Proper mode was expected\n");
380 mode_count += 5;
381 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
382 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
383 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
384 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
386 if (mode_count_comp)
388 mode_count = mode_count_comp - 1;
389 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
390 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
391 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
392 ok(mode_count == mode_count_comp - 1, "Got unexpected mode_count %u, expected %u.\n",
393 mode_count, mode_count_comp - 1);
395 else
397 skip("Not enough modes for test, skipping.\n");
400 HeapFree(GetProcessHeap(), 0, modes);
401 IDXGIOutput_Release(output);
402 IDXGIAdapter_Release(adapter);
403 refcount = IDXGIDevice_Release(device);
404 ok(!refcount, "Device has %u references left.\n", refcount);
407 struct refresh_rates
409 UINT numerator;
410 UINT denominator;
411 BOOL numerator_should_pass;
412 BOOL denominator_should_pass;
415 static void test_create_swapchain(void)
417 DXGI_SWAP_CHAIN_DESC creation_desc, result_desc;
418 ULONG refcount, expected_refcount;
419 IDXGISwapChain *swapchain;
420 IUnknown *obj, *parent;
421 IDXGIAdapter *adapter;
422 IDXGIFactory *factory;
423 IDXGIDevice *device;
424 HRESULT hr;
425 UINT i;
427 const struct refresh_rates refresh_list[] =
429 {60, 60, FALSE, FALSE},
430 {60, 0, TRUE, FALSE},
431 {60, 1, TRUE, TRUE},
432 { 0, 60, TRUE, FALSE},
433 { 0, 0, TRUE, FALSE},
436 if (!(device = create_device()))
438 skip("Failed to create device, skipping tests.\n");
439 return;
442 creation_desc.OutputWindow = 0;
443 creation_desc.BufferDesc.Width = 800;
444 creation_desc.BufferDesc.Height = 600;
445 creation_desc.BufferDesc.RefreshRate.Numerator = 60;
446 creation_desc.BufferDesc.RefreshRate.Denominator = 60;
447 creation_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
448 creation_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
449 creation_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
450 creation_desc.SampleDesc.Count = 1;
451 creation_desc.SampleDesc.Quality = 0;
452 creation_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
453 creation_desc.BufferCount = 1;
454 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
455 creation_desc.Windowed = TRUE;
456 creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
457 creation_desc.Flags = 0;
459 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
460 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown\n");
462 hr = IDXGIDevice_GetAdapter(device, &adapter);
463 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
465 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
466 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
468 expected_refcount = get_refcount((IUnknown *)adapter);
469 refcount = get_refcount((IUnknown *)factory);
470 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
471 refcount = get_refcount((IUnknown *)device);
472 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
474 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
475 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
477 refcount = get_refcount((IUnknown *)adapter);
478 ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount);
479 refcount = get_refcount((IUnknown *)factory);
480 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
481 refcount = get_refcount((IUnknown *)device);
482 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
484 hr = IDXGISwapChain_GetDesc(swapchain, NULL);
485 ok(hr == E_INVALIDARG, "GetDesc unexpectedly returned %#x.\n", hr);
487 hr = IDXGISwapChain_GetParent(swapchain, &IID_IUnknown, (void **)&parent);
488 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
489 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
490 refcount = IUnknown_Release(parent);
491 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
493 hr = IDXGISwapChain_GetParent(swapchain, &IID_IDXGIFactory, (void **)&parent);
494 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
495 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
496 refcount = IUnknown_Release(parent);
497 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
499 IDXGISwapChain_Release(swapchain);
501 refcount = get_refcount((IUnknown *)factory);
502 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
504 for (i = 0; i < sizeof(refresh_list)/sizeof(refresh_list[0]); i++)
506 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
507 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
509 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
510 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
512 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
513 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
515 todo_wine_if (!refresh_list[i].numerator_should_pass)
516 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
517 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
519 todo_wine_if (!refresh_list[i].denominator_should_pass)
520 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
521 "Denominator %u is %u.\n", i ,result_desc.BufferDesc.RefreshRate.Denominator);
523 IDXGISwapChain_Release(swapchain);
526 creation_desc.Windowed = FALSE;
528 for (i = 0; i < sizeof(refresh_list)/sizeof(refresh_list[0]); i++)
530 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
531 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
533 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
534 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
536 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
537 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
539 todo_wine_if (!refresh_list[i].numerator_should_pass)
540 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
541 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
543 todo_wine_if (!refresh_list[i].denominator_should_pass)
544 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
545 "Denominator %u is %u.\n", i ,result_desc.BufferDesc.RefreshRate.Denominator);
547 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
548 todo_wine ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
550 IDXGISwapChain_Release(swapchain);
553 IUnknown_Release(obj);
554 refcount = IDXGIDevice_Release(device);
555 ok(!refcount, "Device has %u references left.\n", refcount);
556 refcount = IDXGIAdapter_Release(adapter);
557 ok(!refcount, "Adapter has %u references left.\n", refcount);
558 refcount = IDXGIFactory_Release(factory);
559 ok(!refcount, "Factory has %u references left.\n", refcount);
560 DestroyWindow(creation_desc.OutputWindow);
563 static void test_get_containing_output(void)
565 DXGI_OUTPUT_DESC output_desc, output_desc2;
566 DXGI_SWAP_CHAIN_DESC swapchain_desc;
567 IDXGIOutput *output, *output2;
568 unsigned int output_count;
569 IDXGISwapChain *swapchain;
570 IDXGIFactory *factory;
571 IDXGIAdapter *adapter;
572 IDXGIDevice *device;
573 ULONG refcount;
574 HRESULT hr;
576 if (!(device = create_device()))
578 skip("Failed to create device.\n");
579 return;
582 hr = IDXGIDevice_GetAdapter(device, &adapter);
583 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
585 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
586 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
588 swapchain_desc.BufferDesc.Width = 800;
589 swapchain_desc.BufferDesc.Height = 600;
590 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
591 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
592 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
593 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
594 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
595 swapchain_desc.SampleDesc.Count = 1;
596 swapchain_desc.SampleDesc.Quality = 0;
597 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
598 swapchain_desc.BufferCount = 1;
599 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
600 swapchain_desc.Windowed = TRUE;
601 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
602 swapchain_desc.Flags = 0;
604 output_count = 0;
605 while (IDXGIAdapter_EnumOutputs(adapter, output_count, &output) != DXGI_ERROR_NOT_FOUND)
607 ok(SUCCEEDED(hr), "Failed to enumarate output %u, hr %#x.\n", output_count, hr);
608 IDXGIOutput_Release(output);
609 ++output_count;
612 if (output_count != 1)
614 skip("Adapter has %u outputs.\n", output_count);
615 goto done;
618 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
619 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
621 refcount = get_refcount((IUnknown *)output);
622 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
624 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
625 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
627 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
628 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
629 "GetContainingOutput failed, hr %#x.\n", hr);
630 if (hr == DXGI_ERROR_UNSUPPORTED)
632 IDXGISwapChain_Release(swapchain);
633 IDXGIOutput_Release(output);
634 goto done;
637 refcount = get_refcount((IUnknown *)output);
638 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
639 refcount = get_refcount((IUnknown *)output2);
640 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
642 hr = IDXGIOutput_GetDesc(output, &output_desc);
643 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
644 hr = IDXGIOutput_GetDesc(output2, &output_desc2);
645 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
647 ok(!lstrcmpW(output_desc.DeviceName, output_desc2.DeviceName),
648 "Got unexpected device name %s, expected %s.\n",
649 wine_dbgstr_w(output_desc.DeviceName), wine_dbgstr_w(output_desc2.DeviceName));
650 ok(!memcmp(&output_desc.DesktopCoordinates, &output_desc2.DesktopCoordinates,
651 sizeof(output_desc.DesktopCoordinates)),
652 "Got unexpected desktop coordinates {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
653 output_desc.DesktopCoordinates.left, output_desc.DesktopCoordinates.top,
654 output_desc.DesktopCoordinates.right, output_desc.DesktopCoordinates.bottom,
655 output_desc2.DesktopCoordinates.left, output_desc2.DesktopCoordinates.top,
656 output_desc2.DesktopCoordinates.right, output_desc2.DesktopCoordinates.bottom);
658 refcount = IDXGIOutput_Release(output2);
659 ok(!refcount, "IDXGIOuput has %u references left.\n", refcount);
661 refcount = IDXGISwapChain_Release(swapchain);
662 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
664 refcount = IDXGIOutput_Release(output);
665 ok(!refcount, "IDXGIOuput has %u references left.\n", refcount);
667 done:
668 refcount = IDXGIDevice_Release(device);
669 ok(!refcount, "Device has %u references left.\n", refcount);
670 refcount = IDXGIAdapter_Release(adapter);
671 ok(!refcount, "Adapter has %u references left.\n", refcount);
672 refcount = IDXGIFactory_Release(factory);
673 ok(!refcount, "Factory has %u references left.\n", refcount);
674 DestroyWindow(swapchain_desc.OutputWindow);
677 static void test_create_factory(void)
679 IDXGIFactory1 *factory;
680 IUnknown *iface;
681 HRESULT hr;
683 iface = (void *)0xdeadbeef;
684 hr = CreateDXGIFactory(&IID_IDXGIDevice, (void **)&iface);
685 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
686 ok(!iface, "Got unexpected iface %p.\n", iface);
688 hr = CreateDXGIFactory(&IID_IUnknown, (void **)&iface);
689 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
690 IUnknown_Release(iface);
692 hr = CreateDXGIFactory(&IID_IDXGIObject, (void **)&iface);
693 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
694 IUnknown_Release(iface);
696 factory = (void *)0xdeadbeef;
697 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&iface);
698 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
699 hr = IUnknown_QueryInterface(iface, &IID_IDXGIFactory1, (void **)&factory);
700 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
701 ok(!factory, "Got unexpected factory %p.\n", factory);
702 IUnknown_Release(iface);
704 iface = (void *)0xdeadbeef;
705 hr = CreateDXGIFactory(&IID_IDXGIFactory1, (void **)&iface);
706 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
707 ok(!iface, "Got unexpected iface %p.\n", iface);
709 if (!pCreateDXGIFactory1)
711 win_skip("CreateDXGIFactory1 not available, skipping tests.\n");
712 return;
715 iface = (void *)0xdeadbeef;
716 hr = pCreateDXGIFactory1(&IID_IDXGIDevice, (void **)&iface);
717 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
718 ok(!iface, "Got unexpected iface %p.\n", iface);
720 hr = pCreateDXGIFactory1(&IID_IUnknown, (void **)&iface);
721 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
722 IUnknown_Release(iface);
724 hr = pCreateDXGIFactory1(&IID_IDXGIObject, (void **)&iface);
725 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
726 IUnknown_Release(iface);
728 hr = pCreateDXGIFactory1(&IID_IDXGIFactory, (void **)&iface);
729 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
730 hr = IUnknown_QueryInterface(iface, &IID_IDXGIFactory1, (void **)&factory);
731 ok(SUCCEEDED(hr), "Failed to query IDXGIFactory1 interface, hr %#x.\n", hr);
732 IDXGIFactory1_Release(factory);
733 IUnknown_Release(iface);
735 hr = pCreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&iface);
736 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory1, hr %#x.\n", hr);
737 IUnknown_Release(iface);
740 static void test_private_data(void)
742 ULONG refcount, expected_refcount;
743 IDXGIDevice *device;
744 HRESULT hr;
745 IDXGIDevice *test_object;
746 IUnknown *ptr;
747 static const DWORD data[] = {1, 2, 3, 4};
748 UINT size;
749 static const GUID dxgi_private_data_test_guid =
751 0xfdb37466,
752 0x428f,
753 0x4edf,
754 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
756 static const GUID dxgi_private_data_test_guid2 =
758 0x2e5afac2,
759 0x87b5,
760 0x4c10,
761 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
764 if (!(device = create_device()))
766 skip("Failed to create device, skipping tests.\n");
767 return;
770 test_object = create_device();
772 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
773 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
774 * NULL interface is not considered a clear but as setting an interface pointer that
775 * happens to be NULL. */
776 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 0, NULL);
777 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
778 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
779 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
780 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
781 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
782 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
783 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
785 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
786 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
787 size = sizeof(ptr) * 2;
788 ptr = (IUnknown *)0xdeadbeef;
789 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
790 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
791 ok(!ptr, "Got unexpected pointer %p.\n", ptr);
792 ok(size == sizeof(IUnknown *), "Got unexpected size %u.\n", size);
794 refcount = get_refcount((IUnknown *)test_object);
795 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
796 (IUnknown *)test_object);
797 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
798 expected_refcount = refcount + 1;
799 refcount = get_refcount((IUnknown *)test_object);
800 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
801 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
802 (IUnknown *)test_object);
803 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
804 refcount = get_refcount((IUnknown *)test_object);
805 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
807 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
808 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
809 expected_refcount--;
810 refcount = get_refcount((IUnknown *)test_object);
811 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
813 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
814 (IUnknown *)test_object);
815 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
816 size = sizeof(data);
817 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, size, data);
818 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
819 refcount = get_refcount((IUnknown *)test_object);
820 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
821 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
822 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
823 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
824 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
826 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
827 (IUnknown *)test_object);
828 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
829 expected_refcount++;
830 size = 2 * sizeof(ptr);
831 ptr = NULL;
832 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
833 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
834 ok(size == sizeof(test_object), "Got unexpected size %u.\n", size);
835 expected_refcount++;
836 refcount = get_refcount((IUnknown *)test_object);
837 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
838 if (ptr)
839 IUnknown_Release(ptr);
840 expected_refcount--;
842 ptr = (IUnknown *)0xdeadbeef;
843 size = 1;
844 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
845 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
846 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
847 size = 2 * sizeof(ptr);
848 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
849 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
850 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
851 refcount = get_refcount((IUnknown *)test_object);
852 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
854 size = 1;
855 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
856 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
857 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
858 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
859 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, NULL, NULL);
860 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
861 size = 0xdeadbabe;
862 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, &size, &ptr);
863 ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
864 ok(size == 0, "Got unexpected size %u.\n", size);
865 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
866 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, NULL, &ptr);
867 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
868 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
870 refcount = IDXGIDevice_Release(device);
871 ok(!refcount, "Device has %u references left.\n", refcount);
872 refcount = IDXGIDevice_Release(test_object);
873 ok(!refcount, "Test object has %u references left.\n", refcount);
876 static void test_swapchain_resize(void)
878 DXGI_SWAP_CHAIN_DESC swapchain_desc;
879 D3D10_TEXTURE2D_DESC texture_desc;
880 DXGI_SURFACE_DESC surface_desc;
881 IDXGISwapChain *swapchain;
882 ID3D10Texture2D *texture;
883 IDXGISurface *surface;
884 IDXGIAdapter *adapter;
885 IDXGIFactory *factory;
886 IDXGIDevice *device;
887 RECT client_rect, r;
888 ULONG refcount;
889 HWND window;
890 HRESULT hr;
891 BOOL ret;
893 if (!(device = create_device()))
895 skip("Failed to create device, skipping tests.\n");
896 return;
898 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
899 0, 0, 640, 480, NULL, NULL, NULL, NULL);
900 ret = GetClientRect(window, &client_rect);
901 ok(ret, "Failed to get client rect.\n");
903 hr = IDXGIDevice_GetAdapter(device, &adapter);
904 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
905 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
906 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
907 IDXGIAdapter_Release(adapter);
909 swapchain_desc.BufferDesc.Width = 640;
910 swapchain_desc.BufferDesc.Height = 480;
911 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
912 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
913 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
914 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
915 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
916 swapchain_desc.SampleDesc.Count = 1;
917 swapchain_desc.SampleDesc.Quality = 0;
918 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
919 swapchain_desc.BufferCount = 1;
920 swapchain_desc.OutputWindow = window;
921 swapchain_desc.Windowed = TRUE;
922 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
923 swapchain_desc.Flags = 0;
925 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
926 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
927 IDXGIFactory_Release(factory);
928 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
929 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
930 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
931 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
933 ret = GetClientRect(window, &r);
934 ok(ret, "Failed to get client rect.\n");
935 ok(EqualRect(&r, &client_rect), "Got unexpected rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
936 r.left, r.top, r.right, r.bottom,
937 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
939 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
940 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
941 ok(swapchain_desc.BufferDesc.Width == 640,
942 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
943 ok(swapchain_desc.BufferDesc.Height == 480,
944 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
945 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
946 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
947 swapchain_desc.BufferDesc.RefreshRate.Numerator);
948 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
949 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
950 swapchain_desc.BufferDesc.RefreshRate.Denominator);
951 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
952 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
953 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
954 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
955 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
956 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
957 ok(swapchain_desc.SampleDesc.Count == 1,
958 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
959 ok(!swapchain_desc.SampleDesc.Quality,
960 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
961 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
962 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
963 ok(swapchain_desc.BufferCount == 1,
964 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
965 ok(swapchain_desc.OutputWindow == window,
966 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
967 ok(swapchain_desc.Windowed,
968 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
969 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
970 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
971 ok(!swapchain_desc.Flags,
972 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
974 hr = IDXGISurface_GetDesc(surface, &surface_desc);
975 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
976 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
977 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
978 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
979 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
980 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
982 ID3D10Texture2D_GetDesc(texture, &texture_desc);
983 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
984 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
985 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
986 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
987 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
988 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
989 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
990 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
991 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
992 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
993 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
995 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
996 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
998 ret = GetClientRect(window, &r);
999 ok(ret, "Failed to get client rect.\n");
1000 ok(EqualRect(&r, &client_rect), "Got unexpected rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
1001 r.left, r.top, r.right, r.bottom,
1002 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
1004 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1005 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
1006 ok(swapchain_desc.BufferDesc.Width == 640,
1007 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
1008 ok(swapchain_desc.BufferDesc.Height == 480,
1009 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
1010 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
1011 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
1012 swapchain_desc.BufferDesc.RefreshRate.Numerator);
1013 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
1014 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
1015 swapchain_desc.BufferDesc.RefreshRate.Denominator);
1016 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
1017 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
1018 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
1019 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
1020 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
1021 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
1022 ok(swapchain_desc.SampleDesc.Count == 1,
1023 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
1024 ok(!swapchain_desc.SampleDesc.Quality,
1025 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
1026 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
1027 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
1028 ok(swapchain_desc.BufferCount == 1,
1029 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
1030 ok(swapchain_desc.OutputWindow == window,
1031 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
1032 ok(swapchain_desc.Windowed,
1033 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
1034 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
1035 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
1036 ok(!swapchain_desc.Flags,
1037 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
1039 hr = IDXGISurface_GetDesc(surface, &surface_desc);
1040 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1041 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
1042 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
1043 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
1044 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
1045 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
1047 ID3D10Texture2D_GetDesc(texture, &texture_desc);
1048 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
1049 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
1050 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
1051 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
1052 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
1053 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
1054 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
1055 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
1056 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
1057 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
1058 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
1060 ID3D10Texture2D_Release(texture);
1061 IDXGISurface_Release(surface);
1062 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
1063 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
1064 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1065 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1066 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
1067 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1069 ret = GetClientRect(window, &r);
1070 ok(ret, "Failed to get client rect.\n");
1071 ok(EqualRect(&r, &client_rect), "Got unexpected rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
1072 r.left, r.top, r.right, r.bottom,
1073 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
1075 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1076 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
1077 ok(swapchain_desc.BufferDesc.Width == 320,
1078 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
1079 ok(swapchain_desc.BufferDesc.Height == 240,
1080 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
1081 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
1082 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
1083 swapchain_desc.BufferDesc.RefreshRate.Numerator);
1084 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
1085 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
1086 swapchain_desc.BufferDesc.RefreshRate.Denominator);
1087 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
1088 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
1089 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
1090 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
1091 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
1092 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
1093 ok(swapchain_desc.SampleDesc.Count == 1,
1094 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
1095 ok(!swapchain_desc.SampleDesc.Quality,
1096 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
1097 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
1098 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
1099 ok(swapchain_desc.BufferCount == 1,
1100 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
1101 ok(swapchain_desc.OutputWindow == window,
1102 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
1103 ok(swapchain_desc.Windowed,
1104 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
1105 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
1106 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
1107 ok(!swapchain_desc.Flags,
1108 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
1110 hr = IDXGISurface_GetDesc(surface, &surface_desc);
1111 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1112 ok(surface_desc.Width == 320, "Got unexpected Width %u.\n", surface_desc.Width);
1113 ok(surface_desc.Height == 240, "Got unexpected Height %u.\n", surface_desc.Height);
1114 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", surface_desc.Format);
1115 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
1116 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
1118 ID3D10Texture2D_GetDesc(texture, &texture_desc);
1119 ok(texture_desc.Width == 320, "Got unexpected Width %u.\n", texture_desc.Width);
1120 ok(texture_desc.Height == 240, "Got unexpected Height %u.\n", texture_desc.Height);
1121 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
1122 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
1123 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", texture_desc.Format);
1124 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
1125 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
1126 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
1127 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
1128 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
1129 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
1131 ID3D10Texture2D_Release(texture);
1132 IDXGISurface_Release(surface);
1134 hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
1135 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
1137 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1138 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
1139 ok(swapchain_desc.BufferDesc.Width == client_rect.right - client_rect.left,
1140 "Got unexpected BufferDesc.Width %u, expected %u.\n",
1141 swapchain_desc.BufferDesc.Width, client_rect.right - client_rect.left);
1142 ok(swapchain_desc.BufferDesc.Height == client_rect.bottom - client_rect.top,
1143 "Got unexpected bufferDesc.Height %u, expected %u.\n",
1144 swapchain_desc.BufferDesc.Height, client_rect.bottom - client_rect.top);
1145 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
1146 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
1147 swapchain_desc.BufferDesc.RefreshRate.Numerator);
1148 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
1149 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
1150 swapchain_desc.BufferDesc.RefreshRate.Denominator);
1151 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
1152 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
1153 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
1154 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
1155 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
1156 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
1157 ok(swapchain_desc.SampleDesc.Count == 1,
1158 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
1159 ok(!swapchain_desc.SampleDesc.Quality,
1160 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
1161 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
1162 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
1163 ok(swapchain_desc.BufferCount == 1,
1164 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
1165 ok(swapchain_desc.OutputWindow == window,
1166 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
1167 ok(swapchain_desc.Windowed,
1168 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
1169 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
1170 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
1171 ok(!swapchain_desc.Flags,
1172 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
1174 IDXGISwapChain_Release(swapchain);
1175 refcount = IDXGIDevice_Release(device);
1176 ok(!refcount, "Device has %u references left.\n", refcount);
1177 DestroyWindow(window);
1180 static void test_swapchain_parameters(void)
1182 IDXGISwapChain *swapchain;
1183 IUnknown *obj;
1184 IDXGIAdapter *adapter;
1185 IDXGIFactory *factory;
1186 IDXGIDevice *device;
1187 IDXGIResource *resource;
1188 DXGI_SWAP_CHAIN_DESC desc;
1189 HRESULT hr;
1190 unsigned int i, j;
1191 ULONG refcount;
1192 DXGI_USAGE usage, expected_usage, broken_usage;
1193 HWND window;
1194 static const struct
1196 BOOL windowed;
1197 UINT buffer_count;
1198 DXGI_SWAP_EFFECT swap_effect;
1199 HRESULT hr, vista_hr;
1200 UINT highest_accessible_buffer;
1202 tests[] =
1204 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1205 {TRUE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
1206 {TRUE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
1207 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1208 {TRUE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
1209 {TRUE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
1210 {TRUE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
1211 {TRUE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1212 {TRUE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1213 {TRUE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1214 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1215 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1216 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
1217 {TRUE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
1218 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1219 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1220 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
1221 {TRUE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1222 {TRUE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1223 {TRUE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1224 {TRUE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
1225 {TRUE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
1226 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
1227 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
1228 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1229 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1230 {TRUE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1231 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1233 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1234 {FALSE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
1235 {FALSE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
1236 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1237 {FALSE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
1238 {FALSE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
1239 {FALSE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
1240 {FALSE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1241 {FALSE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1242 {FALSE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1243 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1244 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1245 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
1246 {FALSE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
1247 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1248 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1249 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
1250 {FALSE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1251 {FALSE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1252 {FALSE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1253 {FALSE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
1254 {FALSE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
1255 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
1256 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
1257 * process. Disable it for now.
1258 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
1260 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1261 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1262 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1263 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
1266 if (!(device = create_device()))
1268 skip("Failed to create device, skipping tests.\n");
1269 return;
1271 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1272 0, 0, 640, 480, 0, 0, 0, 0);
1274 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
1275 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown\n");
1277 hr = IDXGIDevice_GetAdapter(device, &adapter);
1278 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1280 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1281 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1283 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1285 memset(&desc, 0, sizeof(desc));
1286 desc.BufferDesc.Width = registry_mode.dmPelsWidth;
1287 desc.BufferDesc.Height = registry_mode.dmPelsHeight;
1288 desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1289 desc.SampleDesc.Count = 1;
1290 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1291 desc.OutputWindow = window;
1293 desc.Windowed = tests[i].windowed;
1294 desc.BufferCount = tests[i].buffer_count;
1295 desc.SwapEffect = tests[i].swap_effect;
1297 hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
1298 ok(hr == tests[i].hr || broken(hr == tests[i].vista_hr)
1299 || (SUCCEEDED(tests[i].hr) && hr == DXGI_STATUS_OCCLUDED),
1300 "Got unexpected hr %#x, test %u.\n", hr, i);
1301 if (FAILED(hr))
1302 continue;
1304 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
1305 todo_wine ok(SUCCEEDED(hr), "GetBuffer(0) failed, hr %#x, test %u.\n", hr, i);
1306 if (FAILED(hr))
1308 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1309 todo_wine ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1311 IDXGISwapChain_Release(swapchain);
1312 continue;
1315 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
1316 if (tests[i].swap_effect == DXGI_SWAP_EFFECT_DISCARD)
1317 expected_usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
1318 hr = IDXGIResource_GetUsage(resource, &usage);
1319 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
1320 ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
1322 IDXGIResource_Release(resource);
1324 hr = IDXGISwapChain_GetDesc(swapchain, &desc);
1325 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
1327 for (j = 1; j <= tests[i].highest_accessible_buffer; j++)
1329 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
1330 ok(SUCCEEDED(hr), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr, i, j);
1332 /* Buffers > 0 are supposed to be read only. This is the case except that in
1333 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
1334 * writable. This is not the case if an unsupported refresh rate is passed
1335 * for some reason, probably because the invalid refresh rate triggers a
1336 * kinda-sorta windowed mode.
1338 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
1339 * broken.
1341 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
1342 * the draw on the screen right away (Aero on or off doesn't matter), but
1343 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
1345 * Note that if the application doesn't have focused creating a fullscreen
1346 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
1347 * so use the Windowed property of the swapchain that was actually created. */
1348 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_READ_ONLY;
1349 broken_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
1351 if (desc.Windowed || j < tests[i].highest_accessible_buffer)
1352 broken_usage |= DXGI_USAGE_READ_ONLY;
1354 hr = IDXGIResource_GetUsage(resource, &usage);
1355 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u, buffer %u.\n", hr, i, j);
1356 ok(usage == expected_usage || broken(usage == broken_usage), "Got usage %x, expected %x, test %u, buffer %u.\n",
1357 usage, expected_usage, i, j);
1359 IDXGIResource_Release(resource);
1361 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
1362 ok(hr == DXGI_ERROR_INVALID_CALL, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j, hr, i);
1364 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1365 todo_wine ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1367 IDXGISwapChain_Release(swapchain);
1370 IDXGIFactory_Release(factory);
1371 IDXGIAdapter_Release(adapter);
1372 IUnknown_Release(obj);
1373 refcount = IDXGIDevice_Release(device);
1374 ok(!refcount, "Device has %u references left.\n", refcount);
1375 DestroyWindow(window);
1378 static void test_maximum_frame_latency(void)
1380 IDXGIDevice1 *device1;
1381 IDXGIDevice *device;
1382 UINT max_latency;
1383 ULONG refcount;
1384 HRESULT hr;
1386 if (!(device = create_device()))
1388 skip("Failed to create device.\n");
1389 return;
1392 if (SUCCEEDED(IDXGIDevice_QueryInterface(device, &IID_IDXGIDevice1, (void **)&device1)))
1394 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
1395 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1396 ok(max_latency == DEFAULT_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
1398 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY);
1399 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1400 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
1401 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1402 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
1404 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY + 1);
1405 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1406 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
1407 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1408 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
1410 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, 0);
1411 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1412 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
1413 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1414 /* 0 does not reset to the default frame latency on all Windows versions. */
1415 ok(max_latency == DEFAULT_FRAME_LATENCY || broken(!max_latency),
1416 "Got unexpected maximum frame latency %u.\n", max_latency);
1418 IDXGIDevice1_Release(device1);
1420 else
1422 win_skip("IDXGIDevice1 is not implemented.\n");
1425 refcount = IDXGIDevice_Release(device);
1426 ok(!refcount, "Device has %u references left.\n", refcount);
1429 static void test_output_desc(void)
1431 IDXGIAdapter *adapter, *adapter2;
1432 IDXGIOutput *output, *output2;
1433 DXGI_OUTPUT_DESC desc;
1434 IDXGIFactory *factory;
1435 unsigned int i, j;
1436 ULONG refcount;
1437 HRESULT hr;
1439 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory);
1440 ok(SUCCEEDED(hr), "Failed to create DXGI factory, hr %#x.\n", hr);
1442 for (i = 0; ; ++i)
1444 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter);
1445 if (hr == DXGI_ERROR_NOT_FOUND)
1446 break;
1447 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
1449 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter2);
1450 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
1451 ok(adapter != adapter2, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter, adapter2);
1452 refcount = get_refcount((IUnknown *)adapter);
1453 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
1454 IDXGIAdapter_Release(adapter2);
1456 refcount = get_refcount((IUnknown *)factory);
1457 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
1458 refcount = get_refcount((IUnknown *)adapter);
1459 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
1461 for (j = 0; ; ++j)
1463 MONITORINFOEXW monitor_info;
1464 BOOL ret;
1466 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output);
1467 if (hr == DXGI_ERROR_NOT_FOUND)
1468 break;
1469 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
1471 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output2);
1472 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
1473 ok(output != output2, "Expected to get new instance of IDXGIOuput, %p == %p.\n", output, output2);
1474 refcount = get_refcount((IUnknown *)output);
1475 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
1476 IDXGIOutput_Release(output2);
1478 refcount = get_refcount((IUnknown *)factory);
1479 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
1480 refcount = get_refcount((IUnknown *)adapter);
1481 ok(refcount == 2, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
1482 refcount = get_refcount((IUnknown *)output);
1483 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
1485 hr = IDXGIOutput_GetDesc(output, NULL);
1486 ok(hr == E_INVALIDARG, "Got unexpected hr %#x for output %u on adapter %u.\n", hr, j, i);
1487 hr = IDXGIOutput_GetDesc(output, &desc);
1488 ok(SUCCEEDED(hr), "Failed to get desc for output %u on adapter %u, hr %#x.\n", j, i, hr);
1490 monitor_info.cbSize = sizeof(monitor_info);
1491 ret = GetMonitorInfoW(desc.Monitor, (MONITORINFO *)&monitor_info);
1492 ok(ret, "Failed to get monitor info.\n");
1493 ok(!lstrcmpW(desc.DeviceName, monitor_info.szDevice), "Got unexpected device name %s, expected %s.\n",
1494 wine_dbgstr_w(desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
1495 ok(!memcmp(&desc.DesktopCoordinates, &monitor_info.rcMonitor, sizeof(desc.DesktopCoordinates)),
1496 "Got unexpected desktop coordinates {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
1497 desc.DesktopCoordinates.left, desc.DesktopCoordinates.top,
1498 desc.DesktopCoordinates.right, desc.DesktopCoordinates.bottom,
1499 monitor_info.rcMonitor.left, monitor_info.rcMonitor.top,
1500 monitor_info.rcMonitor.right, monitor_info.rcMonitor.bottom);
1502 IDXGIOutput_Release(output);
1503 refcount = get_refcount((IUnknown *)adapter);
1504 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
1507 IDXGIAdapter_Release(adapter);
1508 refcount = get_refcount((IUnknown *)factory);
1509 ok(refcount == 1, "Get unexpected refcount %u.\n", refcount);
1512 refcount = IDXGIFactory_Release(factory);
1513 ok(!refcount, "IDXGIFactory has %u references left.\n", refcount);
1516 START_TEST(device)
1518 pCreateDXGIFactory1 = (void *)GetProcAddress(GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1");
1520 registry_mode.dmSize = sizeof(registry_mode);
1521 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
1523 test_adapter_desc();
1524 test_check_interface_support();
1525 test_create_surface();
1526 test_parents();
1527 test_output();
1528 test_create_swapchain();
1529 test_get_containing_output();
1530 test_create_factory();
1531 test_private_data();
1532 test_swapchain_resize();
1533 test_swapchain_parameters();
1534 test_maximum_frame_latency();
1535 test_output_desc();