kernel32/tests: Add a test to check some fields in fake dlls.
[wine.git] / dlls / dxgi / factory.c
blob52c145bc6a8edddf0a6a48082dab48208ae99fa2
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
20 #include "config.h"
21 #include "wine/port.h"
23 #include "dxgi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dxgi);
27 static inline struct dxgi_factory *impl_from_IWineDXGIFactory(IWineDXGIFactory *iface)
29 return CONTAINING_RECORD(iface, struct dxgi_factory, IWineDXGIFactory_iface);
32 static HRESULT STDMETHODCALLTYPE dxgi_factory_QueryInterface(IWineDXGIFactory *iface, REFIID iid, void **out)
34 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
36 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
38 if (IsEqualGUID(iid, &IID_IWineDXGIFactory)
39 || IsEqualGUID(iid, &IID_IDXGIFactory5)
40 || IsEqualGUID(iid, &IID_IDXGIFactory4)
41 || IsEqualGUID(iid, &IID_IDXGIFactory3)
42 || IsEqualGUID(iid, &IID_IDXGIFactory2)
43 || (factory->extended && IsEqualGUID(iid, &IID_IDXGIFactory1))
44 || IsEqualGUID(iid, &IID_IDXGIFactory)
45 || IsEqualGUID(iid, &IID_IDXGIObject)
46 || IsEqualGUID(iid, &IID_IUnknown))
48 IUnknown_AddRef(iface);
49 *out = iface;
50 return S_OK;
53 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
55 *out = NULL;
56 return E_NOINTERFACE;
59 static ULONG STDMETHODCALLTYPE dxgi_factory_AddRef(IWineDXGIFactory *iface)
61 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
62 ULONG refcount = InterlockedIncrement(&factory->refcount);
64 TRACE("%p increasing refcount to %u.\n", iface, refcount);
66 return refcount;
69 static ULONG STDMETHODCALLTYPE dxgi_factory_Release(IWineDXGIFactory *iface)
71 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
72 ULONG refcount = InterlockedDecrement(&factory->refcount);
74 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
76 if (!refcount)
78 if (factory->device_window)
79 DestroyWindow(factory->device_window);
81 wined3d_mutex_lock();
82 wined3d_decref(factory->wined3d);
83 wined3d_mutex_unlock();
84 wined3d_private_store_cleanup(&factory->private_store);
85 heap_free(factory);
88 return refcount;
91 static HRESULT STDMETHODCALLTYPE dxgi_factory_SetPrivateData(IWineDXGIFactory *iface,
92 REFGUID guid, UINT data_size, const void *data)
94 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
96 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
98 return dxgi_set_private_data(&factory->private_store, guid, data_size, data);
101 static HRESULT STDMETHODCALLTYPE dxgi_factory_SetPrivateDataInterface(IWineDXGIFactory *iface,
102 REFGUID guid, const IUnknown *object)
104 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
106 TRACE("iface %p, guid %s, object %p.\n", iface, debugstr_guid(guid), object);
108 return dxgi_set_private_data_interface(&factory->private_store, guid, object);
111 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetPrivateData(IWineDXGIFactory *iface,
112 REFGUID guid, UINT *data_size, void *data)
114 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
116 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
118 return dxgi_get_private_data(&factory->private_store, guid, data_size, data);
121 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetParent(IWineDXGIFactory *iface, REFIID iid, void **parent)
123 WARN("iface %p, iid %s, parent %p.\n", iface, debugstr_guid(iid), parent);
125 *parent = NULL;
127 return E_NOINTERFACE;
130 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapters1(IWineDXGIFactory *iface,
131 UINT adapter_idx, IDXGIAdapter1 **adapter)
133 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
134 struct dxgi_adapter *adapter_object;
135 UINT adapter_count;
136 HRESULT hr;
138 TRACE("iface %p, adapter_idx %u, adapter %p.\n", iface, adapter_idx, adapter);
140 if (!adapter)
141 return DXGI_ERROR_INVALID_CALL;
143 wined3d_mutex_lock();
144 adapter_count = wined3d_get_adapter_count(factory->wined3d);
145 wined3d_mutex_unlock();
147 if (adapter_idx >= adapter_count)
149 *adapter = NULL;
150 return DXGI_ERROR_NOT_FOUND;
153 if (FAILED(hr = dxgi_adapter_create(factory, adapter_idx, &adapter_object)))
155 *adapter = NULL;
156 return hr;
159 *adapter = (IDXGIAdapter1 *)&adapter_object->IWineDXGIAdapter_iface;
161 TRACE("Returning adapter %p.\n", *adapter);
163 return S_OK;
166 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapters(IWineDXGIFactory *iface,
167 UINT adapter_idx, IDXGIAdapter **adapter)
169 TRACE("iface %p, adapter_idx %u, adapter %p.\n", iface, adapter_idx, adapter);
171 return dxgi_factory_EnumAdapters1(iface, adapter_idx, (IDXGIAdapter1 **)adapter);
174 static HRESULT STDMETHODCALLTYPE dxgi_factory_MakeWindowAssociation(IWineDXGIFactory *iface,
175 HWND window, UINT flags)
177 FIXME("iface %p, window %p, flags %#x stub!\n", iface, window, flags);
179 return S_OK;
182 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetWindowAssociation(IWineDXGIFactory *iface, HWND *window)
184 FIXME("iface %p, window %p stub!\n", iface, window);
186 return E_NOTIMPL;
189 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChain(IWineDXGIFactory *iface,
190 IUnknown *device, DXGI_SWAP_CHAIN_DESC *desc, IDXGISwapChain **swapchain)
192 struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
193 DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
194 DXGI_SWAP_CHAIN_DESC1 swapchain_desc;
196 TRACE("iface %p, device %p, desc %p, swapchain %p.\n", iface, device, desc, swapchain);
198 if (!desc)
200 WARN("Invalid pointer.\n");
201 return DXGI_ERROR_INVALID_CALL;
204 swapchain_desc.Width = desc->BufferDesc.Width;
205 swapchain_desc.Height = desc->BufferDesc.Height;
206 swapchain_desc.Format = desc->BufferDesc.Format;
207 swapchain_desc.Stereo = FALSE;
208 swapchain_desc.SampleDesc = desc->SampleDesc;
209 swapchain_desc.BufferUsage = desc->BufferUsage;
210 swapchain_desc.BufferCount = desc->BufferCount;
211 swapchain_desc.Scaling = DXGI_SCALING_STRETCH;
212 swapchain_desc.SwapEffect = desc->SwapEffect;
213 swapchain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
214 swapchain_desc.Flags = desc->Flags;
216 fullscreen_desc.RefreshRate = desc->BufferDesc.RefreshRate;
217 fullscreen_desc.ScanlineOrdering = desc->BufferDesc.ScanlineOrdering;
218 fullscreen_desc.Scaling = desc->BufferDesc.Scaling;
219 fullscreen_desc.Windowed = desc->Windowed;
221 return IWineDXGIFactory_CreateSwapChainForHwnd(&factory->IWineDXGIFactory_iface,
222 device, desc->OutputWindow, &swapchain_desc, &fullscreen_desc, NULL,
223 (IDXGISwapChain1 **)swapchain);
226 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSoftwareAdapter(IWineDXGIFactory *iface,
227 HMODULE swrast, IDXGIAdapter **adapter)
229 FIXME("iface %p, swrast %p, adapter %p stub!\n", iface, swrast, adapter);
231 return E_NOTIMPL;
234 static BOOL STDMETHODCALLTYPE dxgi_factory_IsCurrent(IWineDXGIFactory *iface)
236 FIXME("iface %p stub!\n", iface);
238 return TRUE;
241 static BOOL STDMETHODCALLTYPE dxgi_factory_IsWindowedStereoEnabled(IWineDXGIFactory *iface)
243 FIXME("iface %p stub!\n", iface);
245 return FALSE;
248 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForHwnd(IWineDXGIFactory *iface,
249 IUnknown *device, HWND window, const DXGI_SWAP_CHAIN_DESC1 *desc,
250 const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,
251 IDXGIOutput *output, IDXGISwapChain1 **swapchain)
253 IWineDXGISwapChainFactory *swapchain_factory;
254 ID3D12CommandQueue *command_queue;
255 HRESULT hr;
257 TRACE("iface %p, device %p, window %p, desc %p, fullscreen_desc %p, output %p, swapchain %p.\n",
258 iface, device, window, desc, fullscreen_desc, output, swapchain);
260 if (!device || !window || !desc || !swapchain)
262 WARN("Invalid pointer.\n");
263 return DXGI_ERROR_INVALID_CALL;
266 if (desc->Stereo)
268 FIXME("Stereo swapchains are not supported.\n");
269 return DXGI_ERROR_UNSUPPORTED;
272 if (!dxgi_validate_swapchain_desc(desc))
273 return DXGI_ERROR_INVALID_CALL;
275 if (output)
276 FIXME("Ignoring output %p.\n", output);
278 if (SUCCEEDED(IUnknown_QueryInterface(device, &IID_IWineDXGISwapChainFactory, (void **)&swapchain_factory)))
280 hr = IWineDXGISwapChainFactory_create_swapchain(swapchain_factory,
281 (IDXGIFactory *)iface, window, desc, fullscreen_desc, output, swapchain);
282 IWineDXGISwapChainFactory_Release(swapchain_factory);
283 return hr;
286 if (SUCCEEDED(IUnknown_QueryInterface(device, &IID_ID3D12CommandQueue, (void **)&command_queue)))
288 hr = d3d12_swapchain_create(iface, command_queue, window, desc, fullscreen_desc, swapchain);
289 ID3D12CommandQueue_Release(command_queue);
290 return hr;
293 ERR("This is not the device we're looking for.\n");
294 return DXGI_ERROR_UNSUPPORTED;
297 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForCoreWindow(IWineDXGIFactory *iface,
298 IUnknown *device, IUnknown *window, const DXGI_SWAP_CHAIN_DESC1 *desc,
299 IDXGIOutput *output, IDXGISwapChain1 **swapchain)
301 FIXME("iface %p, device %p, window %p, desc %p, output %p, swapchain %p stub!\n",
302 iface, device, window, desc, output, swapchain);
304 return E_NOTIMPL;
307 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetSharedResourceAdapterLuid(IWineDXGIFactory *iface,
308 HANDLE resource, LUID *luid)
310 FIXME("iface %p, resource %p, luid %p stub!\n", iface, resource, luid);
312 return E_NOTIMPL;
315 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterOcclusionStatusWindow(IWineDXGIFactory *iface,
316 HWND window, UINT message, DWORD *cookie)
318 FIXME("iface %p, window %p, message %#x, cookie %p stub!\n",
319 iface, window, message, cookie);
321 return E_NOTIMPL;
324 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterStereoStatusEvent(IWineDXGIFactory *iface,
325 HANDLE event, DWORD *cookie)
327 FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
329 return E_NOTIMPL;
332 static void STDMETHODCALLTYPE dxgi_factory_UnregisterStereoStatus(IWineDXGIFactory *iface, DWORD cookie)
334 FIXME("iface %p, cookie %#x stub!\n", iface, cookie);
337 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterStereoStatusWindow(IWineDXGIFactory *iface,
338 HWND window, UINT message, DWORD *cookie)
340 FIXME("iface %p, window %p, message %#x, cookie %p stub!\n",
341 iface, window, message, cookie);
343 return E_NOTIMPL;
346 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterOcclusionStatusEvent(IWineDXGIFactory *iface,
347 HANDLE event, DWORD *cookie)
349 FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
351 return E_NOTIMPL;
354 static void STDMETHODCALLTYPE dxgi_factory_UnregisterOcclusionStatus(IWineDXGIFactory *iface, DWORD cookie)
356 FIXME("iface %p, cookie %#x stub!\n", iface, cookie);
359 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForComposition(IWineDXGIFactory *iface,
360 IUnknown *device, const DXGI_SWAP_CHAIN_DESC1 *desc, IDXGIOutput *output, IDXGISwapChain1 **swapchain)
362 FIXME("iface %p, device %p, desc %p, output %p, swapchain %p stub!\n",
363 iface, device, desc, output, swapchain);
365 return E_NOTIMPL;
368 static UINT STDMETHODCALLTYPE dxgi_factory_GetCreationFlags(IWineDXGIFactory *iface)
370 FIXME("iface %p stub!\n", iface);
372 return 0;
375 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapterByLuid(IWineDXGIFactory *iface,
376 LUID luid, REFIID iid, void **adapter)
378 unsigned int adapter_index;
379 DXGI_ADAPTER_DESC1 desc;
380 IDXGIAdapter1 *adapter1;
381 HRESULT hr;
383 TRACE("iface %p, luid %08x:%08x, iid %s, adapter %p.\n",
384 iface, luid.HighPart, luid.LowPart, debugstr_guid(iid), adapter);
386 adapter_index = 0;
387 while ((hr = dxgi_factory_EnumAdapters1(iface, adapter_index, &adapter1)) == S_OK)
389 if (FAILED(hr = IDXGIAdapter1_GetDesc1(adapter1, &desc)))
391 WARN("Failed to get adapter %u desc, hr %#x.\n", adapter_index, hr);
392 ++adapter_index;
393 continue;
396 if (desc.AdapterLuid.LowPart == luid.LowPart
397 && desc.AdapterLuid.HighPart == luid.HighPart)
399 hr = IDXGIAdapter1_QueryInterface(adapter1, iid, adapter);
400 IDXGIAdapter1_Release(adapter1);
401 return hr;
404 IDXGIAdapter1_Release(adapter1);
405 ++adapter_index;
407 if (hr != DXGI_ERROR_NOT_FOUND)
408 WARN("Failed to enumerate adapters, hr %#x.\n", hr);
410 WARN("Adapter could not be found.\n");
411 return DXGI_ERROR_NOT_FOUND;
414 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumWarpAdapter(IWineDXGIFactory *iface,
415 REFIID iid, void **adapter)
417 FIXME("iface %p, iid %s, adapter %p stub!\n", iface, debugstr_guid(iid), adapter);
419 return E_NOTIMPL;
422 static HRESULT STDMETHODCALLTYPE dxgi_factory_CheckFeatureSupport(IWineDXGIFactory *iface,
423 DXGI_FEATURE feature, void *feature_data, UINT data_size)
425 FIXME("iface %p, feature %#x, feature_data %p, data_size %u stub!\n",
426 iface, feature, feature_data, data_size);
428 return E_NOTIMPL;
431 static const struct IWineDXGIFactoryVtbl dxgi_factory_vtbl =
433 dxgi_factory_QueryInterface,
434 dxgi_factory_AddRef,
435 dxgi_factory_Release,
436 dxgi_factory_SetPrivateData,
437 dxgi_factory_SetPrivateDataInterface,
438 dxgi_factory_GetPrivateData,
439 dxgi_factory_GetParent,
440 dxgi_factory_EnumAdapters,
441 dxgi_factory_MakeWindowAssociation,
442 dxgi_factory_GetWindowAssociation,
443 dxgi_factory_CreateSwapChain,
444 dxgi_factory_CreateSoftwareAdapter,
445 /* IDXGIFactory1 methods */
446 dxgi_factory_EnumAdapters1,
447 dxgi_factory_IsCurrent,
448 /* IDXGIFactory2 methods */
449 dxgi_factory_IsWindowedStereoEnabled,
450 dxgi_factory_CreateSwapChainForHwnd,
451 dxgi_factory_CreateSwapChainForCoreWindow,
452 dxgi_factory_GetSharedResourceAdapterLuid,
453 dxgi_factory_RegisterOcclusionStatusWindow,
454 dxgi_factory_RegisterStereoStatusEvent,
455 dxgi_factory_UnregisterStereoStatus,
456 dxgi_factory_RegisterStereoStatusWindow,
457 dxgi_factory_RegisterOcclusionStatusEvent,
458 dxgi_factory_UnregisterOcclusionStatus,
459 dxgi_factory_CreateSwapChainForComposition,
460 /* IDXGIFactory3 methods */
461 dxgi_factory_GetCreationFlags,
462 /* IDXGIFactory4 methods */
463 dxgi_factory_EnumAdapterByLuid,
464 dxgi_factory_EnumWarpAdapter,
465 /* IDXIGFactory5 methods */
466 dxgi_factory_CheckFeatureSupport,
469 struct dxgi_factory *unsafe_impl_from_IDXGIFactory(IDXGIFactory *iface)
471 IWineDXGIFactory *wine_factory;
472 struct dxgi_factory *factory;
473 HRESULT hr;
475 if (!iface)
476 return NULL;
477 if (FAILED(hr = IDXGIFactory_QueryInterface(iface, &IID_IWineDXGIFactory, (void **)&wine_factory)))
479 ERR("Failed to get IWineDXGIFactory interface, hr %#x.\n", hr);
480 return NULL;
482 assert(wine_factory->lpVtbl == &dxgi_factory_vtbl);
483 factory = CONTAINING_RECORD(wine_factory, struct dxgi_factory, IWineDXGIFactory_iface);
484 IWineDXGIFactory_Release(wine_factory);
485 return factory;
488 static HRESULT dxgi_factory_init(struct dxgi_factory *factory, BOOL extended)
490 factory->IWineDXGIFactory_iface.lpVtbl = &dxgi_factory_vtbl;
491 factory->refcount = 1;
492 wined3d_private_store_init(&factory->private_store);
494 wined3d_mutex_lock();
495 factory->wined3d = wined3d_create(0);
496 wined3d_mutex_unlock();
497 if (!factory->wined3d)
499 wined3d_private_store_cleanup(&factory->private_store);
500 return DXGI_ERROR_UNSUPPORTED;
503 factory->extended = extended;
505 return S_OK;
508 HRESULT dxgi_factory_create(REFIID riid, void **factory, BOOL extended)
510 struct dxgi_factory *object;
511 HRESULT hr;
513 if (!(object = heap_alloc_zero(sizeof(*object))))
514 return E_OUTOFMEMORY;
516 if (FAILED(hr = dxgi_factory_init(object, extended)))
518 WARN("Failed to initialize factory, hr %#x.\n", hr);
519 heap_free(object);
520 return hr;
523 TRACE("Created factory %p.\n", object);
525 hr = IWineDXGIFactory_QueryInterface(&object->IWineDXGIFactory_iface, riid, factory);
526 IWineDXGIFactory_Release(&object->IWineDXGIFactory_iface);
527 return hr;
530 HWND dxgi_factory_get_device_window(struct dxgi_factory *factory)
532 wined3d_mutex_lock();
534 if (!factory->device_window)
536 if (!(factory->device_window = CreateWindowA("static", "DXGI device window",
537 WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, NULL)))
539 wined3d_mutex_unlock();
540 ERR("Failed to create a window.\n");
541 return NULL;
543 TRACE("Created device window %p for factory %p.\n", factory->device_window, factory);
546 wined3d_mutex_unlock();
548 return factory->device_window;