oleaut32: Use a saner calling convention for the marshaller asm thunks.
[wine] / dlls / dxgi / adapter.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 static inline struct dxgi_adapter *impl_from_IWineDXGIAdapter(IWineDXGIAdapter *iface)
28 {
29     return CONTAINING_RECORD(iface, struct dxgi_adapter, IWineDXGIAdapter_iface);
30 }
31
32 /* IUnknown methods */
33
34 static HRESULT STDMETHODCALLTYPE dxgi_adapter_QueryInterface(IWineDXGIAdapter *iface, REFIID riid, void **object)
35 {
36     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
37
38     if (IsEqualGUID(riid, &IID_IUnknown)
39             || IsEqualGUID(riid, &IID_IDXGIObject)
40             || IsEqualGUID(riid, &IID_IDXGIAdapter)
41             || IsEqualGUID(riid, &IID_IWineDXGIAdapter))
42     {
43         IUnknown_AddRef(iface);
44         *object = iface;
45         return S_OK;
46     }
47
48     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
49
50     *object = NULL;
51     return E_NOINTERFACE;
52 }
53
54 static ULONG STDMETHODCALLTYPE dxgi_adapter_AddRef(IWineDXGIAdapter *iface)
55 {
56     struct dxgi_adapter *This = impl_from_IWineDXGIAdapter(iface);
57     ULONG refcount = InterlockedIncrement(&This->refcount);
58
59     TRACE("%p increasing refcount to %u\n", This, refcount);
60
61     return refcount;
62 }
63
64 static ULONG STDMETHODCALLTYPE dxgi_adapter_Release(IWineDXGIAdapter *iface)
65 {
66     struct dxgi_adapter *This = impl_from_IWineDXGIAdapter(iface);
67     ULONG refcount = InterlockedDecrement(&This->refcount);
68
69     TRACE("%p decreasing refcount to %u\n", This, refcount);
70
71     if (!refcount)
72     {
73         IDXGIOutput_Release(This->output);
74         HeapFree(GetProcessHeap(), 0, This);
75     }
76
77     return refcount;
78 }
79
80 /* IDXGIObject methods */
81
82 static HRESULT STDMETHODCALLTYPE dxgi_adapter_SetPrivateData(IWineDXGIAdapter *iface,
83         REFGUID guid, UINT data_size, const void *data)
84 {
85     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n", iface, debugstr_guid(guid), data_size, data);
86
87     return E_NOTIMPL;
88 }
89
90 static HRESULT STDMETHODCALLTYPE dxgi_adapter_SetPrivateDataInterface(IWineDXGIAdapter *iface,
91         REFGUID guid, const IUnknown *object)
92 {
93     FIXME("iface %p, guid %s, object %p stub!\n", iface, debugstr_guid(guid), object);
94
95     return E_NOTIMPL;
96 }
97
98 static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetPrivateData(IWineDXGIAdapter *iface,
99         REFGUID guid, UINT *data_size, void *data)
100 {
101     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n", iface, debugstr_guid(guid), data_size, data);
102
103     return E_NOTIMPL;
104 }
105
106 static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetParent(IWineDXGIAdapter *iface, REFIID riid, void **parent)
107 {
108     struct dxgi_adapter *This = impl_from_IWineDXGIAdapter(iface);
109
110     TRACE("iface %p, riid %s, parent %p\n", iface, debugstr_guid(riid), parent);
111
112     return IWineDXGIFactory_QueryInterface(This->parent, riid, parent);
113 }
114
115 /* IDXGIAdapter methods */
116
117 static HRESULT STDMETHODCALLTYPE dxgi_adapter_EnumOutputs(IWineDXGIAdapter *iface,
118         UINT output_idx, IDXGIOutput **output)
119 {
120     struct dxgi_adapter *This = impl_from_IWineDXGIAdapter(iface);
121
122     TRACE("iface %p, output_idx %u, output %p.\n", iface, output_idx, output);
123
124     if (output_idx > 0)
125     {
126         *output = NULL;
127         return DXGI_ERROR_NOT_FOUND;
128     }
129
130     *output = This->output;
131     IDXGIOutput_AddRef(*output);
132
133     TRACE("Returning output %p.\n", output);
134
135     return S_OK;
136 }
137
138 static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetDesc(IWineDXGIAdapter *iface, DXGI_ADAPTER_DESC *desc)
139 {
140     struct dxgi_adapter *This = impl_from_IWineDXGIAdapter(iface);
141     struct wined3d_adapter_identifier adapter_id;
142     char description[128];
143     struct wined3d *wined3d;
144     HRESULT hr;
145
146     TRACE("iface %p, desc %p.\n", iface, desc);
147
148     if (!desc) return E_INVALIDARG;
149
150     wined3d = IWineDXGIFactory_get_wined3d(This->parent);
151     adapter_id.driver_size = 0;
152     adapter_id.description = description;
153     adapter_id.description_size = sizeof(description);
154     adapter_id.device_name_size = 0;
155
156     EnterCriticalSection(&dxgi_cs);
157     hr = wined3d_get_adapter_identifier(wined3d, This->ordinal, 0, &adapter_id);
158     wined3d_decref(wined3d);
159     LeaveCriticalSection(&dxgi_cs);
160
161     if (SUCCEEDED(hr))
162     {
163         if (!MultiByteToWideChar(CP_ACP, 0, description, -1, desc->Description, 128))
164         {
165             DWORD err = GetLastError();
166             ERR("Failed to translate description %s (%#x).\n", debugstr_a(description), err);
167             hr = E_FAIL;
168         }
169
170         desc->VendorId = adapter_id.vendor_id;
171         desc->DeviceId = adapter_id.device_id;
172         desc->SubSysId = adapter_id.subsystem_id;
173         desc->Revision = adapter_id.revision;
174         desc->DedicatedVideoMemory = adapter_id.video_memory;
175         desc->DedicatedSystemMemory = 0; /* FIXME */
176         desc->SharedSystemMemory = 0; /* FIXME */
177         memcpy(&desc->AdapterLuid, &adapter_id.adapter_luid, sizeof(desc->AdapterLuid));
178     }
179
180     return hr;
181 }
182
183 static HRESULT STDMETHODCALLTYPE dxgi_adapter_CheckInterfaceSupport(IWineDXGIAdapter *iface,
184         REFGUID guid, LARGE_INTEGER *umd_version)
185 {
186     FIXME("iface %p, guid %s, umd_version %p stub!\n", iface, debugstr_guid(guid), umd_version);
187
188     return E_NOTIMPL;
189 }
190
191 /* IWineDXGIAdapter methods */
192
193 static UINT STDMETHODCALLTYPE dxgi_adapter_get_ordinal(IWineDXGIAdapter *iface)
194 {
195     struct dxgi_adapter *This = impl_from_IWineDXGIAdapter(iface);
196
197     TRACE("iface %p, returning %u\n", iface, This->ordinal);
198
199     return This->ordinal;
200 }
201
202 static const struct IWineDXGIAdapterVtbl dxgi_adapter_vtbl =
203 {
204     /* IUnknown methods */
205     dxgi_adapter_QueryInterface,
206     dxgi_adapter_AddRef,
207     dxgi_adapter_Release,
208     /* IDXGIObject methods */
209     dxgi_adapter_SetPrivateData,
210     dxgi_adapter_SetPrivateDataInterface,
211     dxgi_adapter_GetPrivateData,
212     dxgi_adapter_GetParent,
213     /* IDXGIAdapter methods */
214     dxgi_adapter_EnumOutputs,
215     dxgi_adapter_GetDesc,
216     dxgi_adapter_CheckInterfaceSupport,
217     /* IWineDXGIAdapter methods */
218     dxgi_adapter_get_ordinal,
219 };
220
221 HRESULT dxgi_adapter_init(struct dxgi_adapter *adapter, IWineDXGIFactory *parent, UINT ordinal)
222 {
223     struct dxgi_output *output;
224
225     adapter->IWineDXGIAdapter_iface.lpVtbl = &dxgi_adapter_vtbl;
226     adapter->parent = parent;
227     adapter->refcount = 1;
228     adapter->ordinal = ordinal;
229
230     output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*output));
231     if (!output)
232     {
233         return E_OUTOFMEMORY;
234     }
235     dxgi_output_init(output, adapter);
236     adapter->output = &output->IDXGIOutput_iface;
237
238     return S_OK;
239 }