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
21 #include "wine/port.h"
23 #include "dxgi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dxgi
);
27 static inline struct dxgi_factory
*impl_from_IDXGIFactory1(IDXGIFactory1
*iface
)
29 return CONTAINING_RECORD(iface
, struct dxgi_factory
, IDXGIFactory1_iface
);
32 static HRESULT STDMETHODCALLTYPE
dxgi_factory_QueryInterface(IDXGIFactory1
*iface
, REFIID iid
, void **out
)
34 struct dxgi_factory
*factory
= impl_from_IDXGIFactory1(iface
);
36 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
38 if ((factory
->extended
&& IsEqualGUID(iid
, &IID_IDXGIFactory1
))
39 || IsEqualGUID(iid
, &IID_IDXGIFactory
)
40 || IsEqualGUID(iid
, &IID_IDXGIObject
)
41 || IsEqualGUID(iid
, &IID_IUnknown
))
43 IUnknown_AddRef(iface
);
48 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
54 static ULONG STDMETHODCALLTYPE
dxgi_factory_AddRef(IDXGIFactory1
*iface
)
56 struct dxgi_factory
*factory
= impl_from_IDXGIFactory1(iface
);
57 ULONG refcount
= InterlockedIncrement(&factory
->refcount
);
59 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
64 static ULONG STDMETHODCALLTYPE
dxgi_factory_Release(IDXGIFactory1
*iface
)
66 struct dxgi_factory
*factory
= impl_from_IDXGIFactory1(iface
);
67 ULONG refcount
= InterlockedDecrement(&factory
->refcount
);
69 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
75 if (factory
->device_window
)
76 DestroyWindow(factory
->device_window
);
77 for (i
= 0; i
< factory
->adapter_count
; ++i
)
79 IDXGIAdapter1_Release(factory
->adapters
[i
]);
81 HeapFree(GetProcessHeap(), 0, factory
->adapters
);
84 wined3d_decref(factory
->wined3d
);
85 wined3d_mutex_unlock();
86 wined3d_private_store_cleanup(&factory
->private_store
);
87 HeapFree(GetProcessHeap(), 0, factory
);
93 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateData(IDXGIFactory1
*iface
,
94 REFGUID guid
, UINT data_size
, const void *data
)
96 struct dxgi_factory
*factory
= impl_from_IDXGIFactory1(iface
);
98 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
100 return dxgi_set_private_data(&factory
->private_store
, guid
, data_size
, data
);
103 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateDataInterface(IDXGIFactory1
*iface
,
104 REFGUID guid
, const IUnknown
*object
)
106 struct dxgi_factory
*factory
= impl_from_IDXGIFactory1(iface
);
108 TRACE("iface %p, guid %s, object %p.\n", iface
, debugstr_guid(guid
), object
);
110 return dxgi_set_private_data_interface(&factory
->private_store
, guid
, object
);
113 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetPrivateData(IDXGIFactory1
*iface
,
114 REFGUID guid
, UINT
*data_size
, void *data
)
116 struct dxgi_factory
*factory
= impl_from_IDXGIFactory1(iface
);
118 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
120 return dxgi_get_private_data(&factory
->private_store
, guid
, data_size
, data
);
123 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetParent(IDXGIFactory1
*iface
, REFIID iid
, void **parent
)
125 WARN("iface %p, iid %s, parent %p.\n", iface
, debugstr_guid(iid
), parent
);
129 return E_NOINTERFACE
;
132 static HRESULT STDMETHODCALLTYPE
dxgi_factory_EnumAdapters1(IDXGIFactory1
*iface
,
133 UINT adapter_idx
, IDXGIAdapter1
**adapter
)
135 struct dxgi_factory
*factory
= impl_from_IDXGIFactory1(iface
);
137 TRACE("iface %p, adapter_idx %u, adapter %p.\n", iface
, adapter_idx
, adapter
);
140 return DXGI_ERROR_INVALID_CALL
;
142 if (adapter_idx
>= factory
->adapter_count
)
145 return DXGI_ERROR_NOT_FOUND
;
148 *adapter
= (IDXGIAdapter1
*)factory
->adapters
[adapter_idx
];
149 IDXGIAdapter1_AddRef(*adapter
);
151 TRACE("Returning adapter %p.\n", *adapter
);
156 static HRESULT STDMETHODCALLTYPE
dxgi_factory_EnumAdapters(IDXGIFactory1
*iface
,
157 UINT adapter_idx
, IDXGIAdapter
**adapter
)
159 TRACE("iface %p, adapter_idx %u, adapter %p.\n", iface
, adapter_idx
, adapter
);
161 return dxgi_factory_EnumAdapters1(iface
, adapter_idx
, (IDXGIAdapter1
**)adapter
);
164 static HRESULT STDMETHODCALLTYPE
dxgi_factory_MakeWindowAssociation(IDXGIFactory1
*iface
, HWND window
, UINT flags
)
166 FIXME("iface %p, window %p, flags %#x stub!\n", iface
, window
, flags
);
171 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetWindowAssociation(IDXGIFactory1
*iface
, HWND
*window
)
173 FIXME("iface %p, window %p stub!\n", iface
, window
);
178 static UINT
dxgi_rational_to_uint(const DXGI_RATIONAL
*rational
)
180 if (rational
->Denominator
)
181 return rational
->Numerator
/ rational
->Denominator
;
183 return rational
->Numerator
;
186 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSwapChain(IDXGIFactory1
*iface
,
187 IUnknown
*device
, DXGI_SWAP_CHAIN_DESC
*desc
, IDXGISwapChain
**swapchain
)
189 struct wined3d_swapchain
*wined3d_swapchain
;
190 struct wined3d_swapchain_desc wined3d_desc
;
191 IWineDXGIDevice
*dxgi_device
;
193 UINT min_buffer_count
;
195 FIXME("iface %p, device %p, desc %p, swapchain %p partial stub!\n", iface
, device
, desc
, swapchain
);
197 switch (desc
->SwapEffect
)
199 case DXGI_SWAP_EFFECT_DISCARD
:
200 case DXGI_SWAP_EFFECT_SEQUENTIAL
:
201 min_buffer_count
= 1;
204 case DXGI_SWAP_EFFECT_FLIP_DISCARD
:
205 case DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
:
206 min_buffer_count
= 2;
210 WARN("Invalid swap effect %u used, returning DXGI_ERROR_INVALID_CALL.\n", desc
->SwapEffect
);
211 return DXGI_ERROR_INVALID_CALL
;
214 if (desc
->BufferCount
< min_buffer_count
|| desc
->BufferCount
> 16)
216 WARN("BufferCount is %u, returning DXGI_ERROR_INVALID_CALL.\n", desc
->BufferCount
);
217 return DXGI_ERROR_INVALID_CALL
;
219 if (!desc
->OutputWindow
)
221 FIXME("No output window, should use factory output window\n");
224 hr
= IUnknown_QueryInterface(device
, &IID_IWineDXGIDevice
, (void **)&dxgi_device
);
227 ERR("This is not the device we're looking for\n");
231 FIXME("Ignoring SwapEffect and Flags\n");
233 wined3d_desc
.backbuffer_width
= desc
->BufferDesc
.Width
;
234 wined3d_desc
.backbuffer_height
= desc
->BufferDesc
.Height
;
235 wined3d_desc
.backbuffer_format
= wined3dformat_from_dxgi_format(desc
->BufferDesc
.Format
);
236 wined3d_desc
.backbuffer_count
= desc
->BufferCount
;
237 wined3d_sample_desc_from_dxgi(&wined3d_desc
.multisample_type
,
238 &wined3d_desc
.multisample_quality
, &desc
->SampleDesc
);
239 wined3d_desc
.swap_effect
= WINED3D_SWAP_EFFECT_DISCARD
;
240 wined3d_desc
.device_window
= desc
->OutputWindow
;
241 wined3d_desc
.windowed
= desc
->Windowed
;
242 wined3d_desc
.enable_auto_depth_stencil
= FALSE
;
243 wined3d_desc
.auto_depth_stencil_format
= 0;
244 wined3d_desc
.flags
= 0; /* WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL? */
245 wined3d_desc
.refresh_rate
= dxgi_rational_to_uint(&desc
->BufferDesc
.RefreshRate
);
246 wined3d_desc
.swap_interval
= WINED3DPRESENT_INTERVAL_DEFAULT
;
247 wined3d_desc
.auto_restore_display_mode
= TRUE
;
249 hr
= IWineDXGIDevice_create_swapchain(dxgi_device
, &wined3d_desc
, &wined3d_swapchain
);
250 IWineDXGIDevice_Release(dxgi_device
);
253 WARN("Failed to create swapchain, hr %#x.\n", hr
);
257 wined3d_mutex_lock();
258 *swapchain
= wined3d_swapchain_get_parent(wined3d_swapchain
);
259 wined3d_mutex_unlock();
264 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSoftwareAdapter(IDXGIFactory1
*iface
,
265 HMODULE swrast
, IDXGIAdapter
**adapter
)
267 FIXME("iface %p, swrast %p, adapter %p stub!\n", iface
, swrast
, adapter
);
272 static BOOL STDMETHODCALLTYPE
dxgi_factory_IsCurrent(IDXGIFactory1
*iface
)
274 FIXME("iface %p stub!\n", iface
);
279 static const struct IDXGIFactory1Vtbl dxgi_factory_vtbl
=
281 dxgi_factory_QueryInterface
,
283 dxgi_factory_Release
,
284 dxgi_factory_SetPrivateData
,
285 dxgi_factory_SetPrivateDataInterface
,
286 dxgi_factory_GetPrivateData
,
287 dxgi_factory_GetParent
,
288 dxgi_factory_EnumAdapters
,
289 dxgi_factory_MakeWindowAssociation
,
290 dxgi_factory_GetWindowAssociation
,
291 dxgi_factory_CreateSwapChain
,
292 dxgi_factory_CreateSoftwareAdapter
,
293 dxgi_factory_EnumAdapters1
,
294 dxgi_factory_IsCurrent
,
297 struct dxgi_factory
*unsafe_impl_from_IDXGIFactory1(IDXGIFactory1
*iface
)
301 assert(iface
->lpVtbl
== &dxgi_factory_vtbl
);
302 return CONTAINING_RECORD(iface
, struct dxgi_factory
, IDXGIFactory1_iface
);
305 static HRESULT
dxgi_factory_init(struct dxgi_factory
*factory
, BOOL extended
)
310 factory
->IDXGIFactory1_iface
.lpVtbl
= &dxgi_factory_vtbl
;
311 factory
->refcount
= 1;
312 wined3d_private_store_init(&factory
->private_store
);
314 wined3d_mutex_lock();
315 factory
->wined3d
= wined3d_create(0);
316 if (!factory
->wined3d
)
318 wined3d_mutex_unlock();
319 wined3d_private_store_cleanup(&factory
->private_store
);
320 return DXGI_ERROR_UNSUPPORTED
;
323 factory
->adapter_count
= wined3d_get_adapter_count(factory
->wined3d
);
324 wined3d_mutex_unlock();
325 factory
->adapters
= HeapAlloc(GetProcessHeap(), 0, factory
->adapter_count
* sizeof(*factory
->adapters
));
326 if (!factory
->adapters
)
328 ERR("Failed to allocate DXGI adapter array memory.\n");
333 for (i
= 0; i
< factory
->adapter_count
; ++i
)
335 struct dxgi_adapter
*adapter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*adapter
));
340 ERR("Failed to allocate DXGI adapter memory.\n");
342 for (j
= 0; j
< i
; ++j
)
344 IDXGIAdapter1_Release(factory
->adapters
[j
]);
350 if (FAILED(hr
= dxgi_adapter_init(adapter
, factory
, i
)))
354 ERR("Failed to initialize adapter, hr %#x.\n", hr
);
356 HeapFree(GetProcessHeap(), 0, adapter
);
357 for (j
= 0; j
< i
; ++j
)
359 IDXGIAdapter1_Release(factory
->adapters
[j
]);
364 factory
->adapters
[i
] = &adapter
->IDXGIAdapter1_iface
;
367 factory
->extended
= extended
;
372 HeapFree(GetProcessHeap(), 0, factory
->adapters
);
373 wined3d_mutex_lock();
374 wined3d_decref(factory
->wined3d
);
375 wined3d_mutex_unlock();
376 wined3d_private_store_cleanup(&factory
->private_store
);
380 HRESULT
dxgi_factory_create(REFIID riid
, void **factory
, BOOL extended
)
382 struct dxgi_factory
*object
;
385 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
386 return E_OUTOFMEMORY
;
388 if (FAILED(hr
= dxgi_factory_init(object
, extended
)))
390 WARN("Failed to initialize factory, hr %#x.\n", hr
);
391 HeapFree(GetProcessHeap(), 0, object
);
395 TRACE("Created factory %p.\n", object
);
397 hr
= IDXGIFactory1_QueryInterface(&object
->IDXGIFactory1_iface
, riid
, factory
);
398 IDXGIFactory1_Release(&object
->IDXGIFactory1_iface
);
403 HWND
dxgi_factory_get_device_window(struct dxgi_factory
*factory
)
405 wined3d_mutex_lock();
407 if (!factory
->device_window
)
409 if (!(factory
->device_window
= CreateWindowA("static", "DXGI device window",
410 WS_DISABLED
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
)))
412 wined3d_mutex_unlock();
413 ERR("Failed to create a window.\n");
416 TRACE("Created device window %p for factory %p.\n", factory
->device_window
, factory
);
419 wined3d_mutex_unlock();
421 return factory
->device_window
;