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_IDXGIOutput(IDXGIOutput
*iface
)
39 return CONTAINING_RECORD(iface
, struct dxgi_output
, IDXGIOutput_iface
);
42 /* IUnknown methods */
44 static HRESULT STDMETHODCALLTYPE
dxgi_output_QueryInterface(IDXGIOutput
*iface
, REFIID riid
, void **object
)
46 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
48 if (IsEqualGUID(riid
, &IID_IDXGIOutput
)
49 || IsEqualGUID(riid
, &IID_IDXGIObject
)
50 || IsEqualGUID(riid
, &IID_IUnknown
))
52 IUnknown_AddRef(iface
);
57 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
63 static ULONG STDMETHODCALLTYPE
dxgi_output_AddRef(IDXGIOutput
*iface
)
65 struct dxgi_output
*This
= impl_from_IDXGIOutput(iface
);
66 ULONG refcount
= InterlockedIncrement(&This
->refcount
);
68 TRACE("%p increasing refcount to %u.\n", This
, refcount
);
73 static ULONG STDMETHODCALLTYPE
dxgi_output_Release(IDXGIOutput
*iface
)
75 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
76 ULONG refcount
= InterlockedDecrement(&output
->refcount
);
78 TRACE("%p decreasing refcount to %u.\n", output
, refcount
);
82 wined3d_private_store_cleanup(&output
->private_store
);
83 IDXGIAdapter1_Release(&output
->adapter
->IDXGIAdapter1_iface
);
84 HeapFree(GetProcessHeap(), 0, output
);
90 /* IDXGIObject methods */
92 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetPrivateData(IDXGIOutput
*iface
,
93 REFGUID guid
, UINT data_size
, const void *data
)
95 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
97 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
99 return dxgi_set_private_data(&output
->private_store
, guid
, data_size
, data
);
102 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetPrivateDataInterface(IDXGIOutput
*iface
,
103 REFGUID guid
, const IUnknown
*object
)
105 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
107 TRACE("iface %p, guid %s, object %p.\n", iface
, debugstr_guid(guid
), object
);
109 return dxgi_set_private_data_interface(&output
->private_store
, guid
, object
);
112 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetPrivateData(IDXGIOutput
*iface
,
113 REFGUID guid
, UINT
*data_size
, void *data
)
115 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
117 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
119 return dxgi_get_private_data(&output
->private_store
, guid
, data_size
, data
);
122 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetParent(IDXGIOutput
*iface
,
123 REFIID riid
, void **parent
)
125 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
127 TRACE("iface %p, riid %s, parent %p.\n", iface
, debugstr_guid(riid
), parent
);
129 return IDXGIAdapter1_QueryInterface(&output
->adapter
->IDXGIAdapter1_iface
, riid
, parent
);
132 /* IDXGIOutput methods */
134 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDesc(IDXGIOutput
*iface
, DXGI_OUTPUT_DESC
*desc
)
136 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
137 struct wined3d_output_desc wined3d_desc
;
140 TRACE("iface %p, desc %p.\n", iface
, desc
);
145 wined3d_mutex_lock();
146 hr
= wined3d_get_output_desc(output
->adapter
->factory
->wined3d
,
147 output
->adapter
->ordinal
, &wined3d_desc
);
148 wined3d_mutex_unlock();
152 WARN("Failed to get output desc, hr %#x.\n", hr
);
156 memcpy(desc
->DeviceName
, wined3d_desc
.device_name
, sizeof(desc
->DeviceName
));
157 desc
->DesktopCoordinates
= wined3d_desc
.desktop_rect
;
158 desc
->AttachedToDesktop
= wined3d_desc
.attached_to_desktop
;
159 desc
->Rotation
= wined3d_desc
.rotation
;
160 desc
->Monitor
= wined3d_desc
.monitor
;
165 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDisplayModeList(IDXGIOutput
*iface
,
166 DXGI_FORMAT format
, UINT flags
, UINT
*mode_count
, DXGI_MODE_DESC
*desc
)
168 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
169 enum wined3d_format_id wined3d_format
;
170 unsigned int i
, max_count
;
171 struct wined3d
*wined3d
;
173 FIXME("iface %p, format %s, flags %#x, mode_count %p, desc %p partial stub!\n",
174 iface
, debug_dxgi_format(format
), flags
, mode_count
, desc
);
177 return DXGI_ERROR_INVALID_CALL
;
179 if (format
== DXGI_FORMAT_UNKNOWN
)
185 wined3d
= output
->adapter
->factory
->wined3d
;
186 wined3d_format
= wined3dformat_from_dxgi_format(format
);
188 wined3d_mutex_lock();
189 max_count
= wined3d_get_adapter_mode_count(wined3d
, output
->adapter
->ordinal
,
190 wined3d_format
, WINED3D_SCANLINE_ORDERING_UNKNOWN
);
194 wined3d_mutex_unlock();
195 *mode_count
= max_count
;
199 if (max_count
> *mode_count
)
201 wined3d_mutex_unlock();
202 return DXGI_ERROR_MORE_DATA
;
205 *mode_count
= max_count
;
207 for (i
= 0; i
< *mode_count
; ++i
)
209 struct wined3d_display_mode mode
;
212 hr
= wined3d_enum_adapter_modes(wined3d
, output
->adapter
->ordinal
, wined3d_format
,
213 WINED3D_SCANLINE_ORDERING_UNKNOWN
, i
, &mode
);
216 WARN("EnumAdapterModes failed, hr %#x.\n", hr
);
217 wined3d_mutex_unlock();
221 dxgi_mode_from_wined3d(&desc
[i
], &mode
);
223 wined3d_mutex_unlock();
228 static HRESULT STDMETHODCALLTYPE
dxgi_output_FindClosestMatchingMode(IDXGIOutput
*iface
,
229 const DXGI_MODE_DESC
*mode
, DXGI_MODE_DESC
*closest_match
, IUnknown
*device
)
231 struct dxgi_output
*output
= impl_from_IDXGIOutput(iface
);
232 struct wined3d_display_mode wined3d_mode
;
233 struct dxgi_adapter
*adapter
;
234 struct wined3d
*wined3d
;
237 TRACE("iface %p, mode %p, closest_match %p, device %p.\n", iface
, mode
, closest_match
, device
);
239 if ((!mode
->Width
&& mode
->Height
) || (mode
->Width
&& !mode
->Height
))
240 return DXGI_ERROR_INVALID_CALL
;
242 if (mode
->Format
== DXGI_FORMAT_UNKNOWN
&& !device
)
243 return DXGI_ERROR_INVALID_CALL
;
245 TRACE("Mode: %s.\n", debug_dxgi_mode(mode
));
246 if (mode
->Format
== DXGI_FORMAT_UNKNOWN
)
248 FIXME("Matching formats to device not implemented.\n");
252 adapter
= output
->adapter
;
253 wined3d
= adapter
->factory
->wined3d
;
255 wined3d_mutex_lock();
256 wined3d_display_mode_from_dxgi(&wined3d_mode
, mode
);
257 hr
= wined3d_find_closest_matching_adapter_mode(wined3d
, adapter
->ordinal
, &wined3d_mode
);
258 wined3d_mutex_unlock();
262 dxgi_mode_from_wined3d(closest_match
, &wined3d_mode
);
263 TRACE("Returning %s.\n", debug_dxgi_mode(closest_match
));
269 static HRESULT STDMETHODCALLTYPE
dxgi_output_WaitForVBlank(IDXGIOutput
*iface
)
271 FIXME("iface %p stub!\n", iface
);
276 static HRESULT STDMETHODCALLTYPE
dxgi_output_TakeOwnership(IDXGIOutput
*iface
, IUnknown
*device
, BOOL exclusive
)
278 FIXME("iface %p, device %p, exclusive %d stub!\n", iface
, device
, exclusive
);
283 static void STDMETHODCALLTYPE
dxgi_output_ReleaseOwnership(IDXGIOutput
*iface
)
285 FIXME("iface %p stub!\n", iface
);
288 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetGammaControlCapabilities(IDXGIOutput
*iface
,
289 DXGI_GAMMA_CONTROL_CAPABILITIES
*gamma_caps
)
291 FIXME("iface %p, gamma_caps %p stub!\n", iface
, gamma_caps
);
296 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetGammaControl(IDXGIOutput
*iface
,
297 const DXGI_GAMMA_CONTROL
*gamma_control
)
299 FIXME("iface %p, gamma_control %p stub!\n", iface
, gamma_control
);
304 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetGammaControl(IDXGIOutput
*iface
, DXGI_GAMMA_CONTROL
*gamma_control
)
306 FIXME("iface %p, gamma_control %p stub!\n", iface
, gamma_control
);
311 static HRESULT STDMETHODCALLTYPE
dxgi_output_SetDisplaySurface(IDXGIOutput
*iface
, IDXGISurface
*surface
)
313 FIXME("iface %p, surface %p stub!\n", iface
, surface
);
318 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetDisplaySurfaceData(IDXGIOutput
*iface
, IDXGISurface
*surface
)
320 FIXME("iface %p, surface %p stub!\n", iface
, surface
);
325 static HRESULT STDMETHODCALLTYPE
dxgi_output_GetFrameStatistics(IDXGIOutput
*iface
, DXGI_FRAME_STATISTICS
*stats
)
327 FIXME("iface %p, stats %p stub!\n", iface
, stats
);
332 static const struct IDXGIOutputVtbl dxgi_output_vtbl
=
334 dxgi_output_QueryInterface
,
337 /* IDXGIObject methods */
338 dxgi_output_SetPrivateData
,
339 dxgi_output_SetPrivateDataInterface
,
340 dxgi_output_GetPrivateData
,
341 dxgi_output_GetParent
,
342 /* IDXGIOutput methods */
344 dxgi_output_GetDisplayModeList
,
345 dxgi_output_FindClosestMatchingMode
,
346 dxgi_output_WaitForVBlank
,
347 dxgi_output_TakeOwnership
,
348 dxgi_output_ReleaseOwnership
,
349 dxgi_output_GetGammaControlCapabilities
,
350 dxgi_output_SetGammaControl
,
351 dxgi_output_GetGammaControl
,
352 dxgi_output_SetDisplaySurface
,
353 dxgi_output_GetDisplaySurfaceData
,
354 dxgi_output_GetFrameStatistics
,
357 static void dxgi_output_init(struct dxgi_output
*output
, struct dxgi_adapter
*adapter
)
359 output
->IDXGIOutput_iface
.lpVtbl
= &dxgi_output_vtbl
;
360 output
->refcount
= 1;
361 wined3d_private_store_init(&output
->private_store
);
362 output
->adapter
= adapter
;
363 IDXGIAdapter1_AddRef(&output
->adapter
->IDXGIAdapter1_iface
);
366 HRESULT
dxgi_output_create(struct dxgi_adapter
*adapter
, struct dxgi_output
**output
)
368 if (!(*output
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**output
))))
369 return E_OUTOFMEMORY
;
371 dxgi_output_init(*output
, adapter
);