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 "dxgi_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dxgi
);
24 static void dxgi_video_memory_info_from_wined3d(DXGI_QUERY_VIDEO_MEMORY_INFO
*info
,
25 const struct wined3d_video_memory_info
*wined3d_info
)
27 info
->Budget
= wined3d_info
->budget
;
28 info
->CurrentUsage
= wined3d_info
->current_usage
;
29 info
->CurrentReservation
= wined3d_info
->current_reservation
;
30 info
->AvailableForReservation
= wined3d_info
->available_reservation
;
33 static inline struct dxgi_adapter
*impl_from_IWineDXGIAdapter(IWineDXGIAdapter
*iface
)
35 return CONTAINING_RECORD(iface
, struct dxgi_adapter
, IWineDXGIAdapter_iface
);
38 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_QueryInterface(IWineDXGIAdapter
*iface
, REFIID iid
, void **out
)
40 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
42 if (IsEqualGUID(iid
, &IID_IWineDXGIAdapter
)
43 || IsEqualGUID(iid
, &IID_IDXGIAdapter4
)
44 || IsEqualGUID(iid
, &IID_IDXGIAdapter3
)
45 || IsEqualGUID(iid
, &IID_IDXGIAdapter2
)
46 || IsEqualGUID(iid
, &IID_IDXGIAdapter1
)
47 || IsEqualGUID(iid
, &IID_IDXGIAdapter
)
48 || IsEqualGUID(iid
, &IID_IDXGIObject
)
49 || IsEqualGUID(iid
, &IID_IUnknown
))
51 IUnknown_AddRef(iface
);
56 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
62 static ULONG STDMETHODCALLTYPE
dxgi_adapter_AddRef(IWineDXGIAdapter
*iface
)
64 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
65 ULONG refcount
= InterlockedIncrement(&adapter
->refcount
);
67 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
72 static ULONG STDMETHODCALLTYPE
dxgi_adapter_Release(IWineDXGIAdapter
*iface
)
74 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
75 ULONG refcount
= InterlockedDecrement(&adapter
->refcount
);
77 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
81 wined3d_private_store_cleanup(&adapter
->private_store
);
82 IWineDXGIFactory_Release(&adapter
->factory
->IWineDXGIFactory_iface
);
89 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateData(IWineDXGIAdapter
*iface
,
90 REFGUID guid
, UINT data_size
, const void *data
)
92 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
94 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
96 return dxgi_set_private_data(&adapter
->private_store
, guid
, data_size
, data
);
99 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateDataInterface(IWineDXGIAdapter
*iface
,
100 REFGUID guid
, const IUnknown
*object
)
102 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
104 TRACE("iface %p, guid %s, object %p.\n", iface
, debugstr_guid(guid
), object
);
106 return dxgi_set_private_data_interface(&adapter
->private_store
, guid
, object
);
109 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetPrivateData(IWineDXGIAdapter
*iface
,
110 REFGUID guid
, UINT
*data_size
, void *data
)
112 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
114 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
116 return dxgi_get_private_data(&adapter
->private_store
, guid
, data_size
, data
);
119 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetParent(IWineDXGIAdapter
*iface
, REFIID iid
, void **parent
)
121 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
123 TRACE("iface %p, iid %s, parent %p.\n", iface
, debugstr_guid(iid
), parent
);
125 return IWineDXGIFactory_QueryInterface(&adapter
->factory
->IWineDXGIFactory_iface
, iid
, parent
);
128 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_EnumOutputs(IWineDXGIAdapter
*iface
,
129 UINT output_idx
, IDXGIOutput
**output
)
131 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
132 struct dxgi_output
*output_object
;
133 unsigned int output_count
;
136 TRACE("iface %p, output_idx %u, output %p.\n", iface
, output_idx
, output
);
141 output_count
= wined3d_adapter_get_output_count(adapter
->wined3d_adapter
);
142 if (output_idx
>= output_count
)
145 return DXGI_ERROR_NOT_FOUND
;
148 if (FAILED(hr
= dxgi_output_create(adapter
, output_idx
, &output_object
)))
154 *output
= (IDXGIOutput
*)&output_object
->IDXGIOutput6_iface
;
156 TRACE("Returning output %p.\n", *output
);
161 static HRESULT
dxgi_adapter_get_desc(struct dxgi_adapter
*adapter
, DXGI_ADAPTER_DESC3
*desc
)
163 char description
[ARRAY_SIZE(desc
->Description
)];
164 struct wined3d_adapter_identifier adapter_id
;
167 adapter_id
.driver_size
= 0;
168 adapter_id
.description
= description
;
169 adapter_id
.description_size
= sizeof(description
);
171 if (FAILED(hr
= wined3d_adapter_get_identifier(adapter
->wined3d_adapter
, 0, &adapter_id
)))
174 if (!MultiByteToWideChar(CP_ACP
, 0, description
, -1, desc
->Description
, ARRAY_SIZE(description
)))
176 DWORD err
= GetLastError();
177 ERR("Failed to translate description %s (%#lx).\n", debugstr_a(description
), err
);
181 desc
->VendorId
= adapter_id
.vendor_id
;
182 desc
->DeviceId
= adapter_id
.device_id
;
183 desc
->SubSysId
= adapter_id
.subsystem_id
;
184 desc
->Revision
= adapter_id
.revision
;
185 desc
->DedicatedVideoMemory
= adapter_id
.video_memory
;
186 desc
->DedicatedSystemMemory
= 0; /* FIXME */
187 desc
->SharedSystemMemory
= adapter_id
.shared_system_memory
;
188 desc
->AdapterLuid
= adapter_id
.adapter_luid
;
190 desc
->GraphicsPreemptionGranularity
= 0; /* FIXME */
191 desc
->ComputePreemptionGranularity
= 0; /* FIXME */
196 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc(IWineDXGIAdapter
*iface
, DXGI_ADAPTER_DESC
*desc
)
198 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
199 DXGI_ADAPTER_DESC3 desc3
;
202 TRACE("iface %p, desc %p.\n", iface
, desc
);
207 if (SUCCEEDED(hr
= dxgi_adapter_get_desc(adapter
, &desc3
)))
208 memcpy(desc
, &desc3
, sizeof(*desc
));
213 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_CheckInterfaceSupport(IWineDXGIAdapter
*iface
,
214 REFGUID guid
, LARGE_INTEGER
*umd_version
)
216 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
217 struct wined3d_adapter_identifier adapter_id
;
218 struct wined3d_caps caps
;
221 TRACE("iface %p, guid %s, umd_version %p.\n", iface
, debugstr_guid(guid
), umd_version
);
223 /* This method works only for D3D10 interfaces. */
224 if (!(IsEqualGUID(guid
, &IID_IDXGIDevice
)
225 || IsEqualGUID(guid
, &IID_ID3D10Device
)
226 || IsEqualGUID(guid
, &IID_ID3D10Device1
)))
228 WARN("Returning DXGI_ERROR_UNSUPPORTED for %s.\n", debugstr_guid(guid
));
229 return DXGI_ERROR_UNSUPPORTED
;
232 adapter_id
.driver_size
= 0;
233 adapter_id
.description_size
= 0;
235 wined3d_mutex_lock();
236 hr
= wined3d_get_device_caps(adapter
->wined3d_adapter
, WINED3D_DEVICE_TYPE_HAL
, &caps
);
238 hr
= wined3d_adapter_get_identifier(adapter
->wined3d_adapter
, 0, &adapter_id
);
239 wined3d_mutex_unlock();
243 if (caps
.max_feature_level
< WINED3D_FEATURE_LEVEL_10
)
244 return DXGI_ERROR_UNSUPPORTED
;
247 *umd_version
= adapter_id
.driver_version
;
252 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc1(IWineDXGIAdapter
*iface
, DXGI_ADAPTER_DESC1
*desc
)
254 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
255 DXGI_ADAPTER_DESC3 desc3
;
258 TRACE("iface %p, desc %p.\n", iface
, desc
);
263 if (SUCCEEDED(hr
= dxgi_adapter_get_desc(adapter
, &desc3
)))
264 memcpy(desc
, &desc3
, sizeof(*desc
));
269 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc2(IWineDXGIAdapter
*iface
, DXGI_ADAPTER_DESC2
*desc
)
271 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
272 DXGI_ADAPTER_DESC3 desc3
;
275 TRACE("iface %p, desc %p.\n", iface
, desc
);
280 if (SUCCEEDED(hr
= dxgi_adapter_get_desc(adapter
, &desc3
)))
281 memcpy(desc
, &desc3
, sizeof(*desc
));
286 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_RegisterHardwareContentProtectionTeardownStatusEvent(
287 IWineDXGIAdapter
*iface
, HANDLE event
, DWORD
*cookie
)
289 FIXME("iface %p, event %p, cookie %p stub!\n", iface
, event
, cookie
);
294 static void STDMETHODCALLTYPE
dxgi_adapter_UnregisterHardwareContentProtectionTeardownStatus(
295 IWineDXGIAdapter
*iface
, DWORD cookie
)
297 FIXME("iface %p, cookie %#lx stub!\n", iface
, cookie
);
300 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_QueryVideoMemoryInfo(IWineDXGIAdapter
*iface
,
301 UINT node_index
, DXGI_MEMORY_SEGMENT_GROUP segment_group
, DXGI_QUERY_VIDEO_MEMORY_INFO
*info
)
303 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
304 struct wined3d_video_memory_info wined3d_info
;
307 TRACE("iface %p, node_index %u, segment_group %#x, info %p.\n",
308 iface
, node_index
, segment_group
, info
);
310 if (SUCCEEDED(hr
= wined3d_adapter_get_video_memory_info(adapter
->wined3d_adapter
, node_index
,
311 (enum wined3d_memory_segment_group
)segment_group
, &wined3d_info
)))
313 dxgi_video_memory_info_from_wined3d(info
, &wined3d_info
);
315 TRACE("Budget 0x%s, usage 0x%s, available for reservation 0x%s, reservation 0x%s.\n",
316 wine_dbgstr_longlong(info
->Budget
), wine_dbgstr_longlong(info
->CurrentUsage
),
317 wine_dbgstr_longlong(info
->AvailableForReservation
),
318 wine_dbgstr_longlong(info
->CurrentReservation
));
324 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetVideoMemoryReservation(IWineDXGIAdapter
*iface
,
325 UINT node_index
, DXGI_MEMORY_SEGMENT_GROUP segment_group
, UINT64 reservation
)
327 FIXME("iface %p, node_index %u, segment_group %#x, reservation 0x%s stub!\n",
328 iface
, node_index
, segment_group
, wine_dbgstr_longlong(reservation
));
333 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_RegisterVideoMemoryBudgetChangeNotificationEvent(
334 IWineDXGIAdapter
*iface
, HANDLE event
, DWORD
*cookie
)
336 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
338 TRACE("iface %p, event %p, cookie %p.\n", iface
, event
, cookie
);
340 if (!event
|| !cookie
)
341 return DXGI_ERROR_INVALID_CALL
;
343 return wined3d_adapter_register_budget_change_notification(adapter
->wined3d_adapter
, event
, cookie
);
346 static void STDMETHODCALLTYPE
dxgi_adapter_UnregisterVideoMemoryBudgetChangeNotification(
347 IWineDXGIAdapter
*iface
, DWORD cookie
)
349 TRACE("iface %p, cookie %#lx.\n", iface
, cookie
);
351 wined3d_adapter_unregister_budget_change_notification(cookie
);
354 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc3(IWineDXGIAdapter
*iface
, DXGI_ADAPTER_DESC3
*desc
)
356 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
358 TRACE("iface %p, desc %p.\n", iface
, desc
);
363 return dxgi_adapter_get_desc(adapter
, desc
);
366 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_get_adapter_info(IWineDXGIAdapter
*iface
,
367 struct wine_dxgi_adapter_info
*info
)
369 struct dxgi_adapter
*adapter
= impl_from_IWineDXGIAdapter(iface
);
370 struct wined3d_adapter_identifier adapter_id
;
373 TRACE("iface %p, info %p.\n", iface
, info
);
375 memset(&adapter_id
, 0, sizeof(adapter_id
));
376 if (SUCCEEDED(hr
= wined3d_adapter_get_identifier(adapter
->wined3d_adapter
, 0, &adapter_id
)))
378 info
->driver_uuid
= adapter_id
.driver_uuid
;
379 info
->device_uuid
= adapter_id
.device_uuid
;
380 info
->vendor_id
= adapter_id
.vendor_id
;
381 info
->device_id
= adapter_id
.device_id
;
382 info
->luid
= adapter_id
.adapter_luid
;
388 static const struct IWineDXGIAdapterVtbl dxgi_adapter_vtbl
=
390 dxgi_adapter_QueryInterface
,
392 dxgi_adapter_Release
,
393 dxgi_adapter_SetPrivateData
,
394 dxgi_adapter_SetPrivateDataInterface
,
395 dxgi_adapter_GetPrivateData
,
396 dxgi_adapter_GetParent
,
397 /* IDXGIAdapter methods */
398 dxgi_adapter_EnumOutputs
,
399 dxgi_adapter_GetDesc
,
400 dxgi_adapter_CheckInterfaceSupport
,
401 /* IDXGIAdapter1 methods */
402 dxgi_adapter_GetDesc1
,
403 /* IDXGIAdapter2 methods */
404 dxgi_adapter_GetDesc2
,
405 /* IDXGIAdapter3 methods */
406 dxgi_adapter_RegisterHardwareContentProtectionTeardownStatusEvent
,
407 dxgi_adapter_UnregisterHardwareContentProtectionTeardownStatus
,
408 dxgi_adapter_QueryVideoMemoryInfo
,
409 dxgi_adapter_SetVideoMemoryReservation
,
410 dxgi_adapter_RegisterVideoMemoryBudgetChangeNotificationEvent
,
411 dxgi_adapter_UnregisterVideoMemoryBudgetChangeNotification
,
412 /* IDXGIAdapter4 methods */
413 dxgi_adapter_GetDesc3
,
414 /* IWineDXGIAdapter methods */
415 dxgi_adapter_get_adapter_info
,
418 struct dxgi_adapter
*unsafe_impl_from_IDXGIAdapter(IDXGIAdapter
*iface
)
420 IWineDXGIAdapter
*wine_adapter
;
421 struct dxgi_adapter
*adapter
;
426 if (FAILED(hr
= IDXGIAdapter_QueryInterface(iface
, &IID_IWineDXGIAdapter
, (void **)&wine_adapter
)))
428 ERR("Failed to get IWineDXGIAdapter interface, hr %#lx.\n", hr
);
431 assert(wine_adapter
->lpVtbl
== &dxgi_adapter_vtbl
);
432 adapter
= CONTAINING_RECORD(wine_adapter
, struct dxgi_adapter
, IWineDXGIAdapter_iface
);
433 IWineDXGIAdapter_Release(wine_adapter
);
437 static void dxgi_adapter_init(struct dxgi_adapter
*adapter
, struct dxgi_factory
*factory
, UINT ordinal
)
439 adapter
->IWineDXGIAdapter_iface
.lpVtbl
= &dxgi_adapter_vtbl
;
440 adapter
->refcount
= 1;
441 adapter
->wined3d_adapter
= wined3d_get_adapter(factory
->wined3d
, ordinal
);
442 wined3d_private_store_init(&adapter
->private_store
);
443 adapter
->ordinal
= ordinal
;
444 adapter
->factory
= factory
;
445 IWineDXGIFactory_AddRef(&adapter
->factory
->IWineDXGIFactory_iface
);
448 HRESULT
dxgi_adapter_create(struct dxgi_factory
*factory
, UINT ordinal
, struct dxgi_adapter
**adapter
)
450 if (!(*adapter
= heap_alloc(sizeof(**adapter
))))
451 return E_OUTOFMEMORY
;
453 dxgi_adapter_init(*adapter
, factory
, ordinal
);