ntdll: Avoid the close-on-exec race with recvmsg() on kernels that support this.
[wine] / dlls / dxgi / factory.c
1 /*
2  * Copyright 2008 Henri Verbeet for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  *
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include "dxgi_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(dxgi);
26
27 /* IUnknown methods */
28
29 static HRESULT STDMETHODCALLTYPE dxgi_factory_QueryInterface(IWineDXGIFactory *iface, REFIID riid, void **object)
30 {
31     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
32
33     if (IsEqualGUID(riid, &IID_IUnknown)
34             || IsEqualGUID(riid, &IID_IDXGIObject)
35             || IsEqualGUID(riid, &IID_IDXGIFactory)
36             || IsEqualGUID(riid, &IID_IWineDXGIFactory))
37     {
38         IUnknown_AddRef(iface);
39         *object = iface;
40         return S_OK;
41     }
42
43     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
44
45     *object = NULL;
46     return E_NOINTERFACE;
47 }
48
49 static ULONG STDMETHODCALLTYPE dxgi_factory_AddRef(IWineDXGIFactory *iface)
50 {
51     struct dxgi_factory *This = (struct dxgi_factory *)iface;
52     ULONG refcount = InterlockedIncrement(&This->refcount);
53
54     TRACE("%p increasing refcount to %u\n", This, refcount);
55
56     return refcount;
57 }
58
59 static ULONG STDMETHODCALLTYPE dxgi_factory_Release(IWineDXGIFactory *iface)
60 {
61     struct dxgi_factory *This = (struct dxgi_factory *)iface;
62     ULONG refcount = InterlockedDecrement(&This->refcount);
63
64     TRACE("%p decreasing refcount to %u\n", This, refcount);
65
66     if (!refcount)
67     {
68         UINT i;
69
70         for (i = 0; i < This->adapter_count; ++i)
71         {
72             IDXGIAdapter_Release(This->adapters[i]);
73         }
74
75         EnterCriticalSection(&dxgi_cs);
76         IWineD3D_Release(This->wined3d);
77         LeaveCriticalSection(&dxgi_cs);
78         HeapFree(GetProcessHeap(), 0, This);
79     }
80
81     return refcount;
82 }
83
84 /* IDXGIObject methods */
85
86 static HRESULT STDMETHODCALLTYPE dxgi_factory_SetPrivateData(IWineDXGIFactory *iface,
87         REFGUID guid, UINT data_size, const void *data)
88 {
89     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n", iface, debugstr_guid(guid), data_size, data);
90
91     return E_NOTIMPL;
92 }
93
94 static HRESULT STDMETHODCALLTYPE dxgi_factory_SetPrivateDataInterface(IWineDXGIFactory *iface,
95         REFGUID guid, const IUnknown *object)
96 {
97     FIXME("iface %p, guid %s, object %p stub!\n", iface, debugstr_guid(guid), object);
98
99     return E_NOTIMPL;
100 }
101
102 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetPrivateData(IWineDXGIFactory *iface,
103         REFGUID guid, UINT *data_size, void *data)
104 {
105     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n", iface, debugstr_guid(guid), data_size, data);
106
107     return E_NOTIMPL;
108 }
109
110 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetParent(IWineDXGIFactory *iface, REFIID riid, void **parent)
111 {
112     FIXME("iface %p, riid %s, parent %p stub!\n", iface, debugstr_guid(riid), parent);
113
114     return E_NOTIMPL;
115 }
116
117 /* IDXGIFactory methods */
118
119 static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapters(IWineDXGIFactory *iface,
120         UINT adapter_idx, IDXGIAdapter **adapter)
121 {
122     struct dxgi_factory *This = (struct dxgi_factory *)iface;
123
124     TRACE("iface %p, adapter_idx %u, adapter %p\n", iface, adapter_idx, adapter);
125
126     if (!adapter) return DXGI_ERROR_INVALID_CALL;
127
128     if (adapter_idx >= This->adapter_count)
129     {
130         *adapter = NULL;
131         return DXGI_ERROR_NOT_FOUND;
132     }
133
134     *adapter = This->adapters[adapter_idx];
135     IDXGIAdapter_AddRef(*adapter);
136
137     TRACE("Returning adapter %p\n", *adapter);
138
139     return S_OK;
140 }
141
142 static HRESULT STDMETHODCALLTYPE dxgi_factory_MakeWindowAssociation(IWineDXGIFactory *iface, HWND window, UINT flags)
143 {
144     FIXME("iface %p, window %p, flags %#x stub!\n\n", iface, window, flags);
145
146     return E_NOTIMPL;
147 }
148
149 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetWindowAssociation(IWineDXGIFactory *iface, HWND *window)
150 {
151     FIXME("iface %p, window %p stub!\n", iface, window);
152
153     return E_NOTIMPL;
154 }
155
156 /* TODO: The DXGI swapchain desc is a bit nicer than WINED3DPRESENT_PARAMETERS,
157  * change wined3d to use a structure more similar to DXGI. */
158 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChain(IWineDXGIFactory *iface,
159         IUnknown *device, DXGI_SWAP_CHAIN_DESC *desc, IDXGISwapChain **swapchain)
160 {
161     WINED3DPRESENT_PARAMETERS present_parameters;
162     IWineD3DSwapChain *wined3d_swapchain;
163     IWineD3DDevice *wined3d_device;
164     IWineDXGIDevice *dxgi_device;
165     UINT count;
166     HRESULT hr;
167
168     FIXME("iface %p, device %p, desc %p, swapchain %p partial stub!\n", iface, device, desc, swapchain);
169
170     hr = IUnknown_QueryInterface(device, &IID_IWineDXGIDevice, (void **)&dxgi_device);
171     if (FAILED(hr))
172     {
173         ERR("This is not the device we're looking for\n");
174         return hr;
175     }
176
177     wined3d_device = IWineDXGIDevice_get_wined3d_device(dxgi_device);
178     IWineDXGIDevice_Release(dxgi_device);
179
180     count = IWineD3DDevice_GetNumberOfSwapChains(wined3d_device);
181     if (count)
182     {
183         FIXME("Only a single swapchain supported.\n");
184         IWineD3DDevice_Release(wined3d_device);
185         return E_FAIL;
186     }
187
188     if (!desc->OutputWindow)
189     {
190         FIXME("No output window, should use factory output window\n");
191     }
192
193     FIXME("Ignoring SwapEffect and Flags\n");
194
195     present_parameters.BackBufferWidth = desc->BufferDesc.Width;
196     present_parameters.BackBufferHeight = desc->BufferDesc.Height;
197     present_parameters.BackBufferFormat = wined3dformat_from_dxgi_format(desc->BufferDesc.Format);
198     present_parameters.BackBufferCount = desc->BufferCount;
199     if (desc->SampleDesc.Count > 1)
200     {
201         present_parameters.MultiSampleType = desc->SampleDesc.Count;
202         present_parameters.MultiSampleQuality = desc->SampleDesc.Quality;
203     }
204     else
205     {
206         present_parameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
207         present_parameters.MultiSampleQuality = 0;
208     }
209     present_parameters.SwapEffect = WINED3DSWAPEFFECT_DISCARD;
210     present_parameters.hDeviceWindow = desc->OutputWindow;
211     present_parameters.Windowed = desc->Windowed;
212     present_parameters.EnableAutoDepthStencil = FALSE;
213     present_parameters.AutoDepthStencilFormat = 0;
214     present_parameters.Flags = 0; /* WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL? */
215     present_parameters.FullScreen_RefreshRateInHz =
216             desc->BufferDesc.RefreshRate.Numerator / desc->BufferDesc.RefreshRate.Denominator;
217     present_parameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
218
219     hr = IWineD3DDevice_Init3D(wined3d_device, &present_parameters);
220     if (FAILED(hr))
221     {
222         WARN("Failed to initialize 3D, returning %#x\n", hr);
223         IWineD3DDevice_Release(wined3d_device);
224         return hr;
225     }
226
227     hr = IWineD3DDevice_GetSwapChain(wined3d_device, 0, &wined3d_swapchain);
228     IWineD3DDevice_Release(wined3d_device);
229     if (FAILED(hr))
230     {
231         WARN("Failed to get swapchain, returning %#x\n", hr);
232         return hr;
233     }
234
235     hr = IWineD3DSwapChain_GetParent(wined3d_swapchain, (IUnknown **)swapchain);
236     IUnknown_Release(wined3d_swapchain);
237     if (FAILED(hr))
238     {
239         WARN("Failed to get swapchain, returning %#x\n", hr);
240         return hr;
241     }
242
243     /* FIXME? The swapchain is created with refcount 1 by the wined3d device,
244      * but the wined3d device can't hold a real reference. */
245     IUnknown_Release(*swapchain);
246
247     TRACE("Created IDXGISwapChain %p\n", *swapchain);
248
249     return S_OK;
250 }
251
252 static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSoftwareAdapter(IWineDXGIFactory *iface,
253         HMODULE swrast, IDXGIAdapter **adapter)
254 {
255     FIXME("iface %p, swrast %p, adapter %p stub!\n", iface, swrast, adapter);
256
257     return E_NOTIMPL;
258 }
259
260 /* IWineDXGIFactory methods */
261
262 static IWineD3D * STDMETHODCALLTYPE dxgi_factory_get_wined3d(IWineDXGIFactory *iface)
263 {
264     struct dxgi_factory *This = (struct dxgi_factory *)iface;
265
266     TRACE("iface %p\n", iface);
267
268     EnterCriticalSection(&dxgi_cs);
269     IWineD3D_AddRef(This->wined3d);
270     LeaveCriticalSection(&dxgi_cs);
271     return This->wined3d;
272 }
273
274 const struct IWineDXGIFactoryVtbl dxgi_factory_vtbl =
275 {
276     /* IUnknown methods */
277     dxgi_factory_QueryInterface,
278     dxgi_factory_AddRef,
279     dxgi_factory_Release,
280     /* IDXGIObject methods */
281     dxgi_factory_SetPrivateData,
282     dxgi_factory_SetPrivateDataInterface,
283     dxgi_factory_GetPrivateData,
284     dxgi_factory_GetParent,
285     /* IDXGIFactory methods */
286     dxgi_factory_EnumAdapters,
287     dxgi_factory_MakeWindowAssociation,
288     dxgi_factory_GetWindowAssociation,
289     dxgi_factory_CreateSwapChain,
290     dxgi_factory_CreateSoftwareAdapter,
291     /* IWineDXGIFactory methods */
292     dxgi_factory_get_wined3d,
293 };