comdlg32: Detach file dialog data after child windows were destroyed.
[wine.git] / dlls / dxgi / factory.c
blobbbef76867a37de26557053a110d111ed37452f95
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 *swapchain_desc,
250 const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,
251 IDXGIOutput *output, IDXGISwapChain1 **swapchain)
253 struct wined3d_swapchain *wined3d_swapchain;
254 struct wined3d_swapchain_desc wined3d_desc;
255 unsigned int min_buffer_count;
256 IWineDXGIDevice *dxgi_device;
257 HRESULT hr;
259 TRACE("iface %p, device %p, window %p, swapchain_desc %p, fullscreen_desc %p, "
260 "output %p, swapchain %p.\n",
261 iface, device, window, swapchain_desc, fullscreen_desc, output, swapchain);
263 if (!device || !window || !swapchain_desc || !swapchain)
265 WARN("Invalid pointer.\n");
266 return DXGI_ERROR_INVALID_CALL;
269 if (swapchain_desc->Stereo)
271 FIXME("Stereo swapchains are not supported.\n");
272 return DXGI_ERROR_UNSUPPORTED;
275 switch (swapchain_desc->SwapEffect)
277 case DXGI_SWAP_EFFECT_DISCARD:
278 wined3d_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
279 min_buffer_count = 1;
280 break;
282 case DXGI_SWAP_EFFECT_SEQUENTIAL:
283 wined3d_desc.swap_effect = WINED3D_SWAP_EFFECT_SEQUENTIAL;
284 min_buffer_count = 1;
285 break;
287 case DXGI_SWAP_EFFECT_FLIP_DISCARD:
288 wined3d_desc.swap_effect = WINED3D_SWAP_EFFECT_FLIP_DISCARD;
289 min_buffer_count = 2;
290 break;
292 case DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL:
293 wined3d_desc.swap_effect = WINED3D_SWAP_EFFECT_FLIP_SEQUENTIAL;
294 min_buffer_count = 2;
295 break;
297 default:
298 WARN("Invalid swap effect %u used.\n", swapchain_desc->SwapEffect);
299 return DXGI_ERROR_INVALID_CALL;
302 if (swapchain_desc->BufferCount < min_buffer_count || swapchain_desc->BufferCount > 16)
304 WARN("BufferCount is %u.\n", swapchain_desc->BufferCount);
305 return DXGI_ERROR_INVALID_CALL;
308 if (FAILED(hr = IUnknown_QueryInterface(device, &IID_IWineDXGIDevice, (void **)&dxgi_device)))
310 ERR("This is not the device we're looking for\n");
311 return hr;
314 if (swapchain_desc->Scaling != DXGI_SCALING_STRETCH)
315 FIXME("Ignoring scaling %#x.\n", swapchain_desc->Scaling);
316 if (swapchain_desc->AlphaMode != DXGI_ALPHA_MODE_IGNORE)
317 FIXME("Ignoring alpha mode %#x.\n", swapchain_desc->AlphaMode);
318 if (fullscreen_desc && fullscreen_desc->ScanlineOrdering)
319 FIXME("Unhandled scanline ordering %#x.\n", fullscreen_desc->ScanlineOrdering);
320 if (fullscreen_desc && fullscreen_desc->Scaling)
321 FIXME("Unhandled mode scaling %#x.\n", fullscreen_desc->Scaling);
323 wined3d_desc.backbuffer_width = swapchain_desc->Width;
324 wined3d_desc.backbuffer_height = swapchain_desc->Height;
325 wined3d_desc.backbuffer_format = wined3dformat_from_dxgi_format(swapchain_desc->Format);
326 wined3d_desc.backbuffer_count = swapchain_desc->BufferCount;
327 wined3d_desc.backbuffer_usage = wined3d_usage_from_dxgi_usage(swapchain_desc->BufferUsage);
328 wined3d_sample_desc_from_dxgi(&wined3d_desc.multisample_type,
329 &wined3d_desc.multisample_quality, &swapchain_desc->SampleDesc);
330 wined3d_desc.device_window = window;
331 wined3d_desc.windowed = fullscreen_desc ? fullscreen_desc->Windowed : TRUE;
332 wined3d_desc.enable_auto_depth_stencil = FALSE;
333 wined3d_desc.auto_depth_stencil_format = 0;
334 wined3d_desc.flags = wined3d_swapchain_flags_from_dxgi(swapchain_desc->Flags);
335 wined3d_desc.refresh_rate = fullscreen_desc ? dxgi_rational_to_uint(&fullscreen_desc->RefreshRate) : 0;
336 wined3d_desc.swap_interval = WINED3D_SWAP_INTERVAL_DEFAULT;
337 wined3d_desc.auto_restore_display_mode = TRUE;
339 hr = IWineDXGIDevice_create_swapchain(dxgi_device, &wined3d_desc, FALSE, &wined3d_swapchain);
340 IWineDXGIDevice_Release(dxgi_device);
341 if (FAILED(hr))
343 WARN("Failed to create swapchain, hr %#x.\n", hr);
344 return hr;
347 wined3d_mutex_lock();
348 *swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
349 wined3d_mutex_unlock();
351 return S_OK;
354 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForCoreWindow(IWineDXGIFactory *iface,
355 IUnknown *device, IUnknown *window, const DXGI_SWAP_CHAIN_DESC1 *desc,
356 IDXGIOutput *output, IDXGISwapChain1 **swapchain)
358 FIXME("iface %p, device %p, window %p, desc %p, output %p, swapchain %p stub!\n",
359 iface, device, window, desc, output, swapchain);
361 return E_NOTIMPL;
364 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetSharedResourceAdapterLuid(IWineDXGIFactory *iface,
365 HANDLE resource, LUID *luid)
367 FIXME("iface %p, resource %p, luid %p stub!\n", iface, resource, luid);
369 return E_NOTIMPL;
372 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterOcclusionStatusWindow(IWineDXGIFactory *iface,
373 HWND window, UINT message, DWORD *cookie)
375 FIXME("iface %p, window %p, message %#x, cookie %p stub!\n",
376 iface, window, message, cookie);
378 return E_NOTIMPL;
381 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterStereoStatusEvent(IWineDXGIFactory *iface,
382 HANDLE event, DWORD *cookie)
384 FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
386 return E_NOTIMPL;
389 static void STDMETHODCALLTYPE dxgi_factory_UnregisterStereoStatus(IWineDXGIFactory *iface, DWORD cookie)
391 FIXME("iface %p, cookie %#x stub!\n", iface, cookie);
394 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterStereoStatusWindow(IWineDXGIFactory *iface,
395 HWND window, UINT message, DWORD *cookie)
397 FIXME("iface %p, window %p, message %#x, cookie %p stub!\n",
398 iface, window, message, cookie);
400 return E_NOTIMPL;
403 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterOcclusionStatusEvent(IWineDXGIFactory *iface,
404 HANDLE event, DWORD *cookie)
406 FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
408 return E_NOTIMPL;
411 static void STDMETHODCALLTYPE dxgi_factory_UnregisterOcclusionStatus(IWineDXGIFactory *iface, DWORD cookie)
413 FIXME("iface %p, cookie %#x stub!\n", iface, cookie);
416 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForComposition(IWineDXGIFactory *iface,
417 IUnknown *device, const DXGI_SWAP_CHAIN_DESC1 *desc, IDXGIOutput *output, IDXGISwapChain1 **swapchain)
419 FIXME("iface %p, device %p, desc %p, output %p, swapchain %p stub!\n",
420 iface, device, desc, output, swapchain);
422 return E_NOTIMPL;
425 static UINT STDMETHODCALLTYPE dxgi_factory_GetCreationFlags(IWineDXGIFactory *iface)
427 FIXME("iface %p stub!\n", iface);
429 return 0;
432 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapterByLuid(IWineDXGIFactory *iface,
433 LUID luid, REFIID iid, void **adapter)
435 unsigned int adapter_index;
436 DXGI_ADAPTER_DESC1 desc;
437 IDXGIAdapter1 *adapter1;
438 HRESULT hr;
440 TRACE("iface %p, luid %08x:%08x, iid %s, adapter %p.\n",
441 iface, luid.HighPart, luid.LowPart, debugstr_guid(iid), adapter);
443 adapter_index = 0;
444 while ((hr = dxgi_factory_EnumAdapters1(iface, adapter_index, &adapter1)) == S_OK)
446 if (FAILED(hr = IDXGIAdapter1_GetDesc1(adapter1, &desc)))
448 WARN("Failed to get adapter %u desc, hr %#x.\n", adapter_index, hr);
449 ++adapter_index;
450 continue;
453 if (desc.AdapterLuid.LowPart == luid.LowPart
454 && desc.AdapterLuid.HighPart == luid.HighPart)
456 hr = IDXGIAdapter1_QueryInterface(adapter1, iid, adapter);
457 IDXGIAdapter1_Release(adapter1);
458 return hr;
461 IDXGIAdapter1_Release(adapter1);
462 ++adapter_index;
464 if (hr != DXGI_ERROR_NOT_FOUND)
465 WARN("Failed to enumerate adapters, hr %#x.\n", hr);
467 WARN("Adapter could not be found.\n");
468 return DXGI_ERROR_NOT_FOUND;
471 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumWarpAdapter(IWineDXGIFactory *iface,
472 REFIID iid, void **adapter)
474 FIXME("iface %p, iid %s, adapter %p stub!\n", iface, debugstr_guid(iid), adapter);
476 return E_NOTIMPL;
479 static HRESULT STDMETHODCALLTYPE dxgi_factory_CheckFeatureSupport(IWineDXGIFactory *iface,
480 DXGI_FEATURE feature, void *feature_data, UINT data_size)
482 FIXME("iface %p, feature %#x, feature_data %p, data_size %u stub!\n",
483 iface, feature, feature_data, data_size);
485 return E_NOTIMPL;
488 static const struct IWineDXGIFactoryVtbl dxgi_factory_vtbl =
490 dxgi_factory_QueryInterface,
491 dxgi_factory_AddRef,
492 dxgi_factory_Release,
493 dxgi_factory_SetPrivateData,
494 dxgi_factory_SetPrivateDataInterface,
495 dxgi_factory_GetPrivateData,
496 dxgi_factory_GetParent,
497 dxgi_factory_EnumAdapters,
498 dxgi_factory_MakeWindowAssociation,
499 dxgi_factory_GetWindowAssociation,
500 dxgi_factory_CreateSwapChain,
501 dxgi_factory_CreateSoftwareAdapter,
502 /* IDXGIFactory1 methods */
503 dxgi_factory_EnumAdapters1,
504 dxgi_factory_IsCurrent,
505 /* IDXGIFactory2 methods */
506 dxgi_factory_IsWindowedStereoEnabled,
507 dxgi_factory_CreateSwapChainForHwnd,
508 dxgi_factory_CreateSwapChainForCoreWindow,
509 dxgi_factory_GetSharedResourceAdapterLuid,
510 dxgi_factory_RegisterOcclusionStatusWindow,
511 dxgi_factory_RegisterStereoStatusEvent,
512 dxgi_factory_UnregisterStereoStatus,
513 dxgi_factory_RegisterStereoStatusWindow,
514 dxgi_factory_RegisterOcclusionStatusEvent,
515 dxgi_factory_UnregisterOcclusionStatus,
516 dxgi_factory_CreateSwapChainForComposition,
517 /* IDXGIFactory3 methods */
518 dxgi_factory_GetCreationFlags,
519 /* IDXGIFactory4 methods */
520 dxgi_factory_EnumAdapterByLuid,
521 dxgi_factory_EnumWarpAdapter,
522 /* IDXIGFactory5 methods */
523 dxgi_factory_CheckFeatureSupport,
526 struct dxgi_factory *unsafe_impl_from_IDXGIFactory(IDXGIFactory *iface)
528 IWineDXGIFactory *wine_factory;
529 struct dxgi_factory *factory;
530 HRESULT hr;
532 if (!iface)
533 return NULL;
534 if (FAILED(hr = IDXGIFactory_QueryInterface(iface, &IID_IWineDXGIFactory, (void **)&wine_factory)))
536 ERR("Failed to get IWineDXGIFactory interface, hr %#x.\n", hr);
537 return NULL;
539 assert(wine_factory->lpVtbl == &dxgi_factory_vtbl);
540 factory = CONTAINING_RECORD(wine_factory, struct dxgi_factory, IWineDXGIFactory_iface);
541 IWineDXGIFactory_Release(wine_factory);
542 return factory;
545 static HRESULT dxgi_factory_init(struct dxgi_factory *factory, BOOL extended)
547 factory->IWineDXGIFactory_iface.lpVtbl = &dxgi_factory_vtbl;
548 factory->refcount = 1;
549 wined3d_private_store_init(&factory->private_store);
551 wined3d_mutex_lock();
552 factory->wined3d = wined3d_create(0);
553 wined3d_mutex_unlock();
554 if (!factory->wined3d)
556 wined3d_private_store_cleanup(&factory->private_store);
557 return DXGI_ERROR_UNSUPPORTED;
560 factory->extended = extended;
562 return S_OK;
565 HRESULT dxgi_factory_create(REFIID riid, void **factory, BOOL extended)
567 struct dxgi_factory *object;
568 HRESULT hr;
570 if (!(object = heap_alloc_zero(sizeof(*object))))
571 return E_OUTOFMEMORY;
573 if (FAILED(hr = dxgi_factory_init(object, extended)))
575 WARN("Failed to initialize factory, hr %#x.\n", hr);
576 heap_free(object);
577 return hr;
580 TRACE("Created factory %p.\n", object);
582 hr = IWineDXGIFactory_QueryInterface(&object->IWineDXGIFactory_iface, riid, factory);
583 IWineDXGIFactory_Release(&object->IWineDXGIFactory_iface);
584 return hr;
587 HWND dxgi_factory_get_device_window(struct dxgi_factory *factory)
589 wined3d_mutex_lock();
591 if (!factory->device_window)
593 if (!(factory->device_window = CreateWindowA("static", "DXGI device window",
594 WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, NULL)))
596 wined3d_mutex_unlock();
597 ERR("Failed to create a window.\n");
598 return NULL;
600 TRACE("Created device window %p for factory %p.\n", factory->device_window, factory);
603 wined3d_mutex_unlock();
605 return factory->device_window;