server: Add a helper for queuing pipe message.
[wine.git] / dlls / dxgi / factory.c
blob698680418f43aebb9dc4c3dbd0ded756a61f85da
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.auto_restore_display_mode = TRUE;
338 hr = IWineDXGIDevice_create_swapchain(dxgi_device, &wined3d_desc, FALSE, &wined3d_swapchain);
339 IWineDXGIDevice_Release(dxgi_device);
340 if (FAILED(hr))
342 WARN("Failed to create swapchain, hr %#x.\n", hr);
343 return hr;
346 wined3d_mutex_lock();
347 *swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
348 wined3d_mutex_unlock();
350 return S_OK;
353 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForCoreWindow(IWineDXGIFactory *iface,
354 IUnknown *device, IUnknown *window, const DXGI_SWAP_CHAIN_DESC1 *desc,
355 IDXGIOutput *output, IDXGISwapChain1 **swapchain)
357 FIXME("iface %p, device %p, window %p, desc %p, output %p, swapchain %p stub!\n",
358 iface, device, window, desc, output, swapchain);
360 return E_NOTIMPL;
363 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetSharedResourceAdapterLuid(IWineDXGIFactory *iface,
364 HANDLE resource, LUID *luid)
366 FIXME("iface %p, resource %p, luid %p stub!\n", iface, resource, luid);
368 return E_NOTIMPL;
371 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterOcclusionStatusWindow(IWineDXGIFactory *iface,
372 HWND window, UINT message, DWORD *cookie)
374 FIXME("iface %p, window %p, message %#x, cookie %p stub!\n",
375 iface, window, message, cookie);
377 return E_NOTIMPL;
380 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterStereoStatusEvent(IWineDXGIFactory *iface,
381 HANDLE event, DWORD *cookie)
383 FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
385 return E_NOTIMPL;
388 static void STDMETHODCALLTYPE dxgi_factory_UnregisterStereoStatus(IWineDXGIFactory *iface, DWORD cookie)
390 FIXME("iface %p, cookie %#x stub!\n", iface, cookie);
393 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterStereoStatusWindow(IWineDXGIFactory *iface,
394 HWND window, UINT message, DWORD *cookie)
396 FIXME("iface %p, window %p, message %#x, cookie %p stub!\n",
397 iface, window, message, cookie);
399 return E_NOTIMPL;
402 static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterOcclusionStatusEvent(IWineDXGIFactory *iface,
403 HANDLE event, DWORD *cookie)
405 FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie);
407 return E_NOTIMPL;
410 static void STDMETHODCALLTYPE dxgi_factory_UnregisterOcclusionStatus(IWineDXGIFactory *iface, DWORD cookie)
412 FIXME("iface %p, cookie %#x stub!\n", iface, cookie);
415 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForComposition(IWineDXGIFactory *iface,
416 IUnknown *device, const DXGI_SWAP_CHAIN_DESC1 *desc, IDXGIOutput *output, IDXGISwapChain1 **swapchain)
418 FIXME("iface %p, device %p, desc %p, output %p, swapchain %p stub!\n",
419 iface, device, desc, output, swapchain);
421 return E_NOTIMPL;
424 static UINT STDMETHODCALLTYPE dxgi_factory_GetCreationFlags(IWineDXGIFactory *iface)
426 FIXME("iface %p stub!\n", iface);
428 return 0;
431 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapterByLuid(IWineDXGIFactory *iface,
432 LUID luid, REFIID iid, void **adapter)
434 unsigned int adapter_index;
435 DXGI_ADAPTER_DESC1 desc;
436 IDXGIAdapter1 *adapter1;
437 HRESULT hr;
439 TRACE("iface %p, luid %08x:%08x, iid %s, adapter %p.\n",
440 iface, luid.HighPart, luid.LowPart, debugstr_guid(iid), adapter);
442 adapter_index = 0;
443 while ((hr = dxgi_factory_EnumAdapters1(iface, adapter_index, &adapter1)) == S_OK)
445 if (FAILED(hr = IDXGIAdapter1_GetDesc1(adapter1, &desc)))
447 WARN("Failed to get adapter %u desc, hr %#x.\n", adapter_index, hr);
448 ++adapter_index;
449 continue;
452 if (desc.AdapterLuid.LowPart == luid.LowPart
453 && desc.AdapterLuid.HighPart == luid.HighPart)
455 hr = IDXGIAdapter1_QueryInterface(adapter1, iid, adapter);
456 IDXGIAdapter1_Release(adapter1);
457 return hr;
460 IDXGIAdapter1_Release(adapter1);
461 ++adapter_index;
463 if (hr != DXGI_ERROR_NOT_FOUND)
464 WARN("Failed to enumerate adapters, hr %#x.\n", hr);
466 WARN("Adapter could not be found.\n");
467 return DXGI_ERROR_NOT_FOUND;
470 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumWarpAdapter(IWineDXGIFactory *iface,
471 REFIID iid, void **adapter)
473 FIXME("iface %p, iid %s, adapter %p stub!\n", iface, debugstr_guid(iid), adapter);
475 return E_NOTIMPL;
478 static HRESULT STDMETHODCALLTYPE dxgi_factory_CheckFeatureSupport(IWineDXGIFactory *iface,
479 DXGI_FEATURE feature, void *feature_data, UINT data_size)
481 FIXME("iface %p, feature %#x, feature_data %p, data_size %u stub!\n",
482 iface, feature, feature_data, data_size);
484 return E_NOTIMPL;
487 static const struct IWineDXGIFactoryVtbl dxgi_factory_vtbl =
489 dxgi_factory_QueryInterface,
490 dxgi_factory_AddRef,
491 dxgi_factory_Release,
492 dxgi_factory_SetPrivateData,
493 dxgi_factory_SetPrivateDataInterface,
494 dxgi_factory_GetPrivateData,
495 dxgi_factory_GetParent,
496 dxgi_factory_EnumAdapters,
497 dxgi_factory_MakeWindowAssociation,
498 dxgi_factory_GetWindowAssociation,
499 dxgi_factory_CreateSwapChain,
500 dxgi_factory_CreateSoftwareAdapter,
501 /* IDXGIFactory1 methods */
502 dxgi_factory_EnumAdapters1,
503 dxgi_factory_IsCurrent,
504 /* IDXGIFactory2 methods */
505 dxgi_factory_IsWindowedStereoEnabled,
506 dxgi_factory_CreateSwapChainForHwnd,
507 dxgi_factory_CreateSwapChainForCoreWindow,
508 dxgi_factory_GetSharedResourceAdapterLuid,
509 dxgi_factory_RegisterOcclusionStatusWindow,
510 dxgi_factory_RegisterStereoStatusEvent,
511 dxgi_factory_UnregisterStereoStatus,
512 dxgi_factory_RegisterStereoStatusWindow,
513 dxgi_factory_RegisterOcclusionStatusEvent,
514 dxgi_factory_UnregisterOcclusionStatus,
515 dxgi_factory_CreateSwapChainForComposition,
516 /* IDXGIFactory3 methods */
517 dxgi_factory_GetCreationFlags,
518 /* IDXGIFactory4 methods */
519 dxgi_factory_EnumAdapterByLuid,
520 dxgi_factory_EnumWarpAdapter,
521 /* IDXIGFactory5 methods */
522 dxgi_factory_CheckFeatureSupport,
525 struct dxgi_factory *unsafe_impl_from_IDXGIFactory(IDXGIFactory *iface)
527 IWineDXGIFactory *wine_factory;
528 struct dxgi_factory *factory;
529 HRESULT hr;
531 if (!iface)
532 return NULL;
533 if (FAILED(hr = IDXGIFactory_QueryInterface(iface, &IID_IWineDXGIFactory, (void **)&wine_factory)))
535 ERR("Failed to get IWineDXGIFactory interface, hr %#x.\n", hr);
536 return NULL;
538 assert(wine_factory->lpVtbl == &dxgi_factory_vtbl);
539 factory = CONTAINING_RECORD(wine_factory, struct dxgi_factory, IWineDXGIFactory_iface);
540 IWineDXGIFactory_Release(wine_factory);
541 return factory;
544 static HRESULT dxgi_factory_init(struct dxgi_factory *factory, BOOL extended)
546 factory->IWineDXGIFactory_iface.lpVtbl = &dxgi_factory_vtbl;
547 factory->refcount = 1;
548 wined3d_private_store_init(&factory->private_store);
550 wined3d_mutex_lock();
551 factory->wined3d = wined3d_create(0);
552 wined3d_mutex_unlock();
553 if (!factory->wined3d)
555 wined3d_private_store_cleanup(&factory->private_store);
556 return DXGI_ERROR_UNSUPPORTED;
559 factory->extended = extended;
561 return S_OK;
564 HRESULT dxgi_factory_create(REFIID riid, void **factory, BOOL extended)
566 struct dxgi_factory *object;
567 HRESULT hr;
569 if (!(object = heap_alloc_zero(sizeof(*object))))
570 return E_OUTOFMEMORY;
572 if (FAILED(hr = dxgi_factory_init(object, extended)))
574 WARN("Failed to initialize factory, hr %#x.\n", hr);
575 heap_free(object);
576 return hr;
579 TRACE("Created factory %p.\n", object);
581 hr = IWineDXGIFactory_QueryInterface(&object->IWineDXGIFactory_iface, riid, factory);
582 IWineDXGIFactory_Release(&object->IWineDXGIFactory_iface);
583 return hr;
586 HWND dxgi_factory_get_device_window(struct dxgi_factory *factory)
588 wined3d_mutex_lock();
590 if (!factory->device_window)
592 if (!(factory->device_window = CreateWindowA("static", "DXGI device window",
593 WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, NULL)))
595 wined3d_mutex_unlock();
596 ERR("Failed to create a window.\n");
597 return NULL;
599 TRACE("Created device window %p for factory %p.\n", factory->device_window, factory);
602 wined3d_mutex_unlock();
604 return factory->device_window;