2 * Copyright 2009 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 "wine/port.h"
22 #include "dxgi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(dxgi
);
26 static void dxgi_mode_from_wined3d(DXGI_MODE_DESC
*mode
, const struct wined3d_display_mode
*wined3d_mode
)
28 mode
->Width
= wined3d_mode
->width
;
29 mode
->Height
= wined3d_mode
->height
;
30 mode
->RefreshRate
.Numerator
= wined3d_mode
->refresh_rate
;
31 mode
->RefreshRate
.Denominator
= 1;
32 mode
->Format
= dxgi_format_from_wined3dformat(wined3d_mode
->format_id
);
33 mode
->ScanlineOrdering
= wined3d_mode
->scanline_ordering
;
34 mode
->Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
; /* FIXME */
37 static inline struct dxgi_output
*impl_from_IDXGIOutput4(IDXGIOutput4
*iface
)
39 return CONTAINING_RECORD(iface
, struct dxgi_output
, IDXGIOutput4_iface
);
42 /* IUnknown methods */
44 static HRESULT STDMETHODCALLTYPE
dxgi_output_QueryInterface(IDXGIOutput4
*iface
, REFIID iid
, void **object
)
46 TRACE("iface %p, iid %s, object %p.\n", iface
, debugstr_guid(iid
), object
);
48 if (IsEqualGUID(iid
, &IID_IDXGIOutput4
)
49 || IsEqualGUID(iid
, &IID_IDXGIOutput3
)
50 || IsEqualGUID(iid
, &IID_IDXGIOutput2
)
51 || IsEqualGUID(iid
, &IID_IDXGIOutput1
)
52 || IsEqualGUID(iid
, &IID_IDXGIOutput
)
53 || IsEqualGUID(iid
, &IID_IDXGIObject
)
54 || IsEqualGUID(iid
, &IID_IUnknown
))
56 IUnknown_AddRef(iface
);
61 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
67 static ULONG STDMETHODCALLTYPE
dxgi_output_AddRef(IDXGIOutput4
*iface
)
69 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
70 ULONG refcount
= InterlockedIncrement(&output
->refcount
);
72 TRACE("%p increasing refcount to %u.\n", output
, refcount
);
77 static ULONG STDMETHODCALLTYPE
dxgi_output_Release(IDXGIOutput4
*iface
)
79 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
80 ULONG refcount
= InterlockedDecrement(&output
->refcount
);
82 TRACE("%p decreasing refcount to %u.\n", output
, refcount
);
86 wined3d_private_store_cleanup(&output
->private_store
);
87 IWineDXGIAdapter_Release(&output
->adapter
->IWineDXGIAdapter_iface
);
94 /* IDXGIObject methods */
96 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetPrivateData(IDXGIOutput4
*iface
,
97 REFGUID guid
, UINT data_size
, const void *data
)
99 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
101 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
103 return dxgi_set_private_data(&output
->private_store
, guid
, data_size
, data
);
106 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetPrivateDataInterface(IDXGIOutput4
*iface
,
107 REFGUID guid
, const IUnknown
*object
)
109 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
111 TRACE("iface %p, guid %s, object %p.\n", iface
, debugstr_guid(guid
), object
);
113 return dxgi_set_private_data_interface(&output
->private_store
, guid
, object
);
116 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetPrivateData(IDXGIOutput4
*iface
,
117 REFGUID guid
, UINT
*data_size
, void *data
)
119 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
121 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
123 return dxgi_get_private_data(&output
->private_store
, guid
, data_size
, data
);
126 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetParent(IDXGIOutput4
*iface
,
127 REFIID riid
, void **parent
)
129 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
131 TRACE("iface %p, riid %s, parent %p.\n", iface
, debugstr_guid(riid
), parent
);
133 return IWineDXGIAdapter_QueryInterface(&output
->adapter
->IWineDXGIAdapter_iface
, riid
, parent
);
136 /* IDXGIOutput methods */
138 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDesc(IDXGIOutput4
*iface
, DXGI_OUTPUT_DESC
*desc
)
140 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
141 struct wined3d_output_desc wined3d_desc
;
144 TRACE("iface %p, desc %p.\n", iface
, desc
);
149 wined3d_mutex_lock();
150 hr
= wined3d_get_output_desc(output
->adapter
->factory
->wined3d
,
151 output
->adapter
->ordinal
, &wined3d_desc
);
152 wined3d_mutex_unlock();
156 WARN("Failed to get output desc, hr %#x.\n", hr
);
160 memcpy(desc
->DeviceName
, wined3d_desc
.device_name
, sizeof(desc
->DeviceName
));
161 desc
->DesktopCoordinates
= wined3d_desc
.desktop_rect
;
162 desc
->AttachedToDesktop
= wined3d_desc
.attached_to_desktop
;
163 desc
->Rotation
= wined3d_desc
.rotation
;
164 desc
->Monitor
= wined3d_desc
.monitor
;
169 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDisplayModeList(IDXGIOutput4
*iface
,
170 DXGI_FORMAT format
, UINT flags
, UINT
*mode_count
, DXGI_MODE_DESC
*desc
)
172 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
173 enum wined3d_format_id wined3d_format
;
174 unsigned int i
, max_count
;
175 struct wined3d
*wined3d
;
177 FIXME("iface %p, format %s, flags %#x, mode_count %p, desc %p partial stub!\n",
178 iface
, debug_dxgi_format(format
), flags
, mode_count
, desc
);
181 return DXGI_ERROR_INVALID_CALL
;
183 if (format
== DXGI_FORMAT_UNKNOWN
)
189 wined3d
= output
->adapter
->factory
->wined3d
;
190 wined3d_format
= wined3dformat_from_dxgi_format(format
);
192 wined3d_mutex_lock();
193 max_count
= wined3d_get_adapter_mode_count(wined3d
, output
->adapter
->ordinal
,
194 wined3d_format
, WINED3D_SCANLINE_ORDERING_UNKNOWN
);
198 wined3d_mutex_unlock();
199 *mode_count
= max_count
;
203 if (max_count
> *mode_count
)
205 wined3d_mutex_unlock();
206 return DXGI_ERROR_MORE_DATA
;
209 *mode_count
= max_count
;
211 for (i
= 0; i
< *mode_count
; ++i
)
213 struct wined3d_display_mode mode
;
216 hr
= wined3d_enum_adapter_modes(wined3d
, output
->adapter
->ordinal
, wined3d_format
,
217 WINED3D_SCANLINE_ORDERING_UNKNOWN
, i
, &mode
);
220 WARN("EnumAdapterModes failed, hr %#x.\n", hr
);
221 wined3d_mutex_unlock();
225 dxgi_mode_from_wined3d(&desc
[i
], &mode
);
227 wined3d_mutex_unlock();
232 static HRESULT STDMETHODCALLTYPE
dxgi_output_FindClosestMatchingMode(IDXGIOutput4
*iface
,
233 const DXGI_MODE_DESC
*mode
, DXGI_MODE_DESC
*closest_match
, IUnknown
*device
)
235 struct dxgi_output
*output
= impl_from_IDXGIOutput4(iface
);
236 struct wined3d_display_mode wined3d_mode
;
237 struct dxgi_adapter
*adapter
;
238 struct wined3d
*wined3d
;
241 TRACE("iface %p, mode %p, closest_match %p, device %p.\n", iface
, mode
, closest_match
, device
);
243 if ((!mode
->Width
&& mode
->Height
) || (mode
->Width
&& !mode
->Height
))
244 return DXGI_ERROR_INVALID_CALL
;
246 if (mode
->Format
== DXGI_FORMAT_UNKNOWN
&& !device
)
247 return DXGI_ERROR_INVALID_CALL
;
249 TRACE("Mode: %s.\n", debug_dxgi_mode(mode
));
250 if (mode
->Format
== DXGI_FORMAT_UNKNOWN
)
252 FIXME("Matching formats to device not implemented.\n");
256 adapter
= output
->adapter
;
257 wined3d
= adapter
->factory
->wined3d
;
259 wined3d_mutex_lock();
260 wined3d_display_mode_from_dxgi(&wined3d_mode
, mode
);
261 hr
= wined3d_find_closest_matching_adapter_mode(wined3d
, adapter
->ordinal
, &wined3d_mode
);
262 wined3d_mutex_unlock();
266 dxgi_mode_from_wined3d(closest_match
, &wined3d_mode
);
267 TRACE("Returning %s.\n", debug_dxgi_mode(closest_match
));
273 static HRESULT STDMETHODCALLTYPE
dxgi_output_WaitForVBlank(IDXGIOutput4
*iface
)
275 static BOOL once
= FALSE
;
278 FIXME("iface %p stub!\n", iface
);
280 TRACE("iface %p stub!\n", iface
);
285 static HRESULT STDMETHODCALLTYPE
dxgi_output_TakeOwnership(IDXGIOutput4
*iface
, IUnknown
*device
, BOOL exclusive
)
287 FIXME("iface %p, device %p, exclusive %d stub!\n", iface
, device
, exclusive
);
292 static void STDMETHODCALLTYPE
dxgi_output_ReleaseOwnership(IDXGIOutput4
*iface
)
294 FIXME("iface %p stub!\n", iface
);
297 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetGammaControlCapabilities(IDXGIOutput4
*iface
,
298 DXGI_GAMMA_CONTROL_CAPABILITIES
*gamma_caps
)
300 FIXME("iface %p, gamma_caps %p stub!\n", iface
, gamma_caps
);
305 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetGammaControl(IDXGIOutput4
*iface
,
306 const DXGI_GAMMA_CONTROL
*gamma_control
)
308 FIXME("iface %p, gamma_control %p stub!\n", iface
, gamma_control
);
313 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetGammaControl(IDXGIOutput4
*iface
, DXGI_GAMMA_CONTROL
*gamma_control
)
315 FIXME("iface %p, gamma_control %p stub!\n", iface
, gamma_control
);
320 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetDisplaySurface(IDXGIOutput4
*iface
, IDXGISurface
*surface
)
322 FIXME("iface %p, surface %p stub!\n", iface
, surface
);
327 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDisplaySurfaceData(IDXGIOutput4
*iface
, IDXGISurface
*surface
)
329 FIXME("iface %p, surface %p stub!\n", iface
, surface
);
334 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetFrameStatistics(IDXGIOutput4
*iface
, DXGI_FRAME_STATISTICS
*stats
)
336 FIXME("iface %p, stats %p stub!\n", iface
, stats
);
341 /* IDXGIOutput1 methods */
343 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDisplayModeList1(IDXGIOutput4
*iface
,
344 DXGI_FORMAT format
, UINT flags
, UINT
*mode_count
, DXGI_MODE_DESC1
*modes
)
346 FIXME("iface %p, format %#x, flags %#x, mode_count %p, modes %p stub!\n",
347 iface
, format
, flags
, mode_count
, modes
);
352 static HRESULT STDMETHODCALLTYPE
dxgi_output_FindClosestMatchingMode1(IDXGIOutput4
*iface
,
353 const DXGI_MODE_DESC1
*mode
, DXGI_MODE_DESC1
*closest_match
, IUnknown
*device
)
355 FIXME("iface %p, mode %p, closest_match %p, device %p stub!\n",
356 iface
, mode
, closest_match
, device
);
361 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDisplaySurfaceData1(IDXGIOutput4
*iface
,
362 IDXGIResource
*resource
)
364 FIXME("iface %p, resource %p stub!\n", iface
, resource
);
369 static HRESULT STDMETHODCALLTYPE
dxgi_output_DuplicateOutput(IDXGIOutput4
*iface
,
370 IUnknown
*device
, IDXGIOutputDuplication
**output_duplication
)
372 FIXME("iface %p, device %p, output_duplication %p stub!\n", iface
, device
, output_duplication
);
377 /* IDXGIOutput2 methods */
379 static BOOL STDMETHODCALLTYPE
dxgi_output_SupportsOverlays(IDXGIOutput4
*iface
)
381 FIXME("iface %p stub!\n", iface
);
386 /* IDXGIOutput3 methods */
388 static HRESULT STDMETHODCALLTYPE
dxgi_output_CheckOverlaySupport(IDXGIOutput4
*iface
,
389 DXGI_FORMAT format
, IUnknown
*device
, UINT
*flags
)
391 FIXME("iface %p, format %#x, device %p, flags %p stub!\n", iface
, format
, device
, flags
);
396 /* IDXGIOutput4 methods */
398 static HRESULT STDMETHODCALLTYPE
dxgi_output_CheckOverlayColorSpaceSupport(IDXGIOutput4
*iface
,
399 DXGI_FORMAT format
, DXGI_COLOR_SPACE_TYPE color_space
, IUnknown
*device
, UINT
*flags
)
401 FIXME("iface %p, format %#x, color_space %#x, device %p, flags %p stub!\n",
402 iface
, format
, color_space
, device
, flags
);
407 static const struct IDXGIOutput4Vtbl dxgi_output_vtbl
=
409 dxgi_output_QueryInterface
,
412 /* IDXGIObject methods */
413 dxgi_output_SetPrivateData
,
414 dxgi_output_SetPrivateDataInterface
,
415 dxgi_output_GetPrivateData
,
416 dxgi_output_GetParent
,
417 /* IDXGIOutput methods */
419 dxgi_output_GetDisplayModeList
,
420 dxgi_output_FindClosestMatchingMode
,
421 dxgi_output_WaitForVBlank
,
422 dxgi_output_TakeOwnership
,
423 dxgi_output_ReleaseOwnership
,
424 dxgi_output_GetGammaControlCapabilities
,
425 dxgi_output_SetGammaControl
,
426 dxgi_output_GetGammaControl
,
427 dxgi_output_SetDisplaySurface
,
428 dxgi_output_GetDisplaySurfaceData
,
429 dxgi_output_GetFrameStatistics
,
430 /* IDXGIOutput1 methods */
431 dxgi_output_GetDisplayModeList1
,
432 dxgi_output_FindClosestMatchingMode1
,
433 dxgi_output_GetDisplaySurfaceData1
,
434 dxgi_output_DuplicateOutput
,
435 /* IDXGIOutput2 methods */
436 dxgi_output_SupportsOverlays
,
437 /* IDXGIOutput3 methods */
438 dxgi_output_CheckOverlaySupport
,
439 /* IDXGIOutput4 methods */
440 dxgi_output_CheckOverlayColorSpaceSupport
,
443 static void dxgi_output_init(struct dxgi_output
*output
, struct dxgi_adapter
*adapter
)
445 output
->IDXGIOutput4_iface
.lpVtbl
= &dxgi_output_vtbl
;
446 output
->refcount
= 1;
447 wined3d_private_store_init(&output
->private_store
);
448 output
->adapter
= adapter
;
449 IWineDXGIAdapter_AddRef(&output
->adapter
->IWineDXGIAdapter_iface
);
452 HRESULT
dxgi_output_create(struct dxgi_adapter
*adapter
, struct dxgi_output
**output
)
454 if (!(*output
= heap_alloc_zero(sizeof(**output
))))
455 return E_OUTOFMEMORY
;
457 dxgi_output_init(*output
, adapter
);