winedbg: Don't dereference possibly NULL thread pointer.
[wine/zf.git] / dlls / dxgi / output.c
blob3ffa5d16408556bc3b6019b1b55c4549cb8d7d38
1 /*
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
19 #include "config.h"
20 #include "wine/port.h"
22 #include "dxgi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(dxgi);
26 static inline DXGI_MODE_SCANLINE_ORDER dxgi_mode_scanline_order_from_wined3d(enum wined3d_scanline_ordering ordering)
28 return (DXGI_MODE_SCANLINE_ORDER)ordering;
31 static void dxgi_mode_from_wined3d(DXGI_MODE_DESC *mode, const struct wined3d_display_mode *wined3d_mode)
33 mode->Width = wined3d_mode->width;
34 mode->Height = wined3d_mode->height;
35 mode->RefreshRate.Numerator = wined3d_mode->refresh_rate;
36 mode->RefreshRate.Denominator = 1;
37 mode->Format = dxgi_format_from_wined3dformat(wined3d_mode->format_id);
38 mode->ScanlineOrdering = dxgi_mode_scanline_order_from_wined3d(wined3d_mode->scanline_ordering);
39 mode->Scaling = DXGI_MODE_SCALING_UNSPECIFIED; /* FIXME */
42 static void dxgi_mode1_from_wined3d(DXGI_MODE_DESC1 *mode, const struct wined3d_display_mode *wined3d_mode)
44 mode->Width = wined3d_mode->width;
45 mode->Height = wined3d_mode->height;
46 mode->RefreshRate.Numerator = wined3d_mode->refresh_rate;
47 mode->RefreshRate.Denominator = 1;
48 mode->Format = dxgi_format_from_wined3dformat(wined3d_mode->format_id);
49 mode->ScanlineOrdering = dxgi_mode_scanline_order_from_wined3d(wined3d_mode->scanline_ordering);
50 mode->Scaling = DXGI_MODE_SCALING_UNSPECIFIED; /* FIXME */
51 mode->Stereo = FALSE; /* FIXME */
54 static HRESULT dxgi_output_find_closest_matching_mode(struct dxgi_output *output,
55 struct wined3d_display_mode *mode, IUnknown *device)
57 HRESULT hr;
59 if (!mode->width != !mode->height)
60 return DXGI_ERROR_INVALID_CALL;
62 if (mode->format_id == WINED3DFMT_UNKNOWN && !device)
63 return DXGI_ERROR_INVALID_CALL;
65 if (mode->format_id == WINED3DFMT_UNKNOWN)
67 FIXME("Matching formats to device not implemented.\n");
68 return E_NOTIMPL;
71 wined3d_mutex_lock();
72 hr = wined3d_output_find_closest_matching_mode(output->wined3d_output, mode);
73 wined3d_mutex_unlock();
75 return hr;
78 static int dxgi_mode_desc_compare(const void *l, const void *r)
80 const DXGI_MODE_DESC *left = l, *right = r;
81 int a, b;
83 if (left->Width != right->Width)
84 return left->Width - right->Width;
86 if (left->Height != right->Height)
87 return left->Height - right->Height;
89 a = left->RefreshRate.Numerator * right->RefreshRate.Denominator;
90 b = right->RefreshRate.Numerator * left->RefreshRate.Denominator;
91 if (a != b)
92 return a - b;
94 return 0;
97 enum dxgi_mode_struct_version
99 DXGI_MODE_STRUCT_VERSION_0,
100 DXGI_MODE_STRUCT_VERSION_1,
103 static HRESULT dxgi_output_get_display_mode_list(struct dxgi_output *output,
104 DXGI_FORMAT format, unsigned int *mode_count, void *modes,
105 enum dxgi_mode_struct_version struct_version)
107 enum wined3d_format_id wined3d_format;
108 struct wined3d_display_mode mode;
109 unsigned int i, max_count;
110 HRESULT hr;
112 if (!mode_count)
113 return DXGI_ERROR_INVALID_CALL;
115 if (format == DXGI_FORMAT_UNKNOWN)
117 *mode_count = 0;
118 return S_OK;
121 wined3d_format = wined3dformat_from_dxgi_format(format);
123 wined3d_mutex_lock();
124 max_count = wined3d_output_get_mode_count(output->wined3d_output,
125 wined3d_format, WINED3D_SCANLINE_ORDERING_UNKNOWN);
127 if (!modes)
129 wined3d_mutex_unlock();
130 *mode_count = max_count;
131 return S_OK;
134 if (max_count > *mode_count)
136 wined3d_mutex_unlock();
137 return DXGI_ERROR_MORE_DATA;
140 *mode_count = max_count;
142 for (i = 0; i < *mode_count; ++i)
144 if (FAILED(hr = wined3d_output_get_mode(output->wined3d_output, wined3d_format,
145 WINED3D_SCANLINE_ORDERING_UNKNOWN, i, &mode)))
147 WARN("Failed to get output mode %u, hr %#x.\n", i, hr);
148 wined3d_mutex_unlock();
149 return hr;
152 switch (struct_version)
154 case DXGI_MODE_STRUCT_VERSION_0:
156 DXGI_MODE_DESC *desc = modes;
157 dxgi_mode_from_wined3d(&desc[i], &mode);
158 break;
161 case DXGI_MODE_STRUCT_VERSION_1:
163 DXGI_MODE_DESC1 *desc = modes;
164 dxgi_mode1_from_wined3d(&desc[i], &mode);
165 break;
169 wined3d_mutex_unlock();
171 switch (struct_version)
173 case DXGI_MODE_STRUCT_VERSION_0:
174 qsort(modes, *mode_count, sizeof(DXGI_MODE_DESC), dxgi_mode_desc_compare);
175 break;
176 case DXGI_MODE_STRUCT_VERSION_1:
177 qsort(modes, *mode_count, sizeof(DXGI_MODE_DESC1), dxgi_mode_desc_compare);
178 break;
181 return S_OK;
184 static inline struct dxgi_output *impl_from_IDXGIOutput6(IDXGIOutput6 *iface)
186 return CONTAINING_RECORD(iface, struct dxgi_output, IDXGIOutput6_iface);
189 /* IUnknown methods */
191 static HRESULT STDMETHODCALLTYPE dxgi_output_QueryInterface(IDXGIOutput6 *iface, REFIID iid, void **object)
193 TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
195 if (IsEqualGUID(iid, &IID_IDXGIOutput6)
196 || IsEqualGUID(iid, &IID_IDXGIOutput5)
197 || IsEqualGUID(iid, &IID_IDXGIOutput4)
198 || IsEqualGUID(iid, &IID_IDXGIOutput3)
199 || IsEqualGUID(iid, &IID_IDXGIOutput2)
200 || IsEqualGUID(iid, &IID_IDXGIOutput1)
201 || IsEqualGUID(iid, &IID_IDXGIOutput)
202 || IsEqualGUID(iid, &IID_IDXGIObject)
203 || IsEqualGUID(iid, &IID_IUnknown))
205 IUnknown_AddRef(iface);
206 *object = iface;
207 return S_OK;
210 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
212 *object = NULL;
213 return E_NOINTERFACE;
216 static ULONG STDMETHODCALLTYPE dxgi_output_AddRef(IDXGIOutput6 *iface)
218 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
219 ULONG refcount = InterlockedIncrement(&output->refcount);
221 TRACE("%p increasing refcount to %u.\n", output, refcount);
223 return refcount;
226 static ULONG STDMETHODCALLTYPE dxgi_output_Release(IDXGIOutput6 *iface)
228 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
229 ULONG refcount = InterlockedDecrement(&output->refcount);
231 TRACE("%p decreasing refcount to %u.\n", output, refcount);
233 if (!refcount)
235 wined3d_private_store_cleanup(&output->private_store);
236 IWineDXGIAdapter_Release(&output->adapter->IWineDXGIAdapter_iface);
237 heap_free(output);
240 return refcount;
243 /* IDXGIObject methods */
245 static HRESULT STDMETHODCALLTYPE dxgi_output_SetPrivateData(IDXGIOutput6 *iface,
246 REFGUID guid, UINT data_size, const void *data)
248 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
250 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
252 return dxgi_set_private_data(&output->private_store, guid, data_size, data);
255 static HRESULT STDMETHODCALLTYPE dxgi_output_SetPrivateDataInterface(IDXGIOutput6 *iface,
256 REFGUID guid, const IUnknown *object)
258 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
260 TRACE("iface %p, guid %s, object %p.\n", iface, debugstr_guid(guid), object);
262 return dxgi_set_private_data_interface(&output->private_store, guid, object);
265 static HRESULT STDMETHODCALLTYPE dxgi_output_GetPrivateData(IDXGIOutput6 *iface,
266 REFGUID guid, UINT *data_size, void *data)
268 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
270 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
272 return dxgi_get_private_data(&output->private_store, guid, data_size, data);
275 static HRESULT STDMETHODCALLTYPE dxgi_output_GetParent(IDXGIOutput6 *iface,
276 REFIID riid, void **parent)
278 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
280 TRACE("iface %p, riid %s, parent %p.\n", iface, debugstr_guid(riid), parent);
282 return IWineDXGIAdapter_QueryInterface(&output->adapter->IWineDXGIAdapter_iface, riid, parent);
285 /* IDXGIOutput methods */
287 static HRESULT STDMETHODCALLTYPE dxgi_output_GetDesc(IDXGIOutput6 *iface, DXGI_OUTPUT_DESC *desc)
289 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
290 struct wined3d_output_desc wined3d_desc;
291 enum wined3d_display_rotation rotation;
292 struct wined3d_display_mode mode;
293 HRESULT hr;
295 TRACE("iface %p, desc %p.\n", iface, desc);
297 if (!desc)
298 return E_INVALIDARG;
300 wined3d_mutex_lock();
301 hr = wined3d_output_get_desc(output->wined3d_output, &wined3d_desc);
302 if (FAILED(hr))
304 WARN("Failed to get output desc, hr %#x.\n", hr);
305 wined3d_mutex_unlock();
306 return hr;
309 hr = wined3d_output_get_display_mode(output->wined3d_output, &mode, &rotation);
310 if (FAILED(hr))
312 WARN("Failed to get output display mode, hr %#x.\n", hr);
313 wined3d_mutex_unlock();
314 return hr;
316 wined3d_mutex_unlock();
318 memcpy(desc->DeviceName, wined3d_desc.device_name, sizeof(desc->DeviceName));
319 desc->DesktopCoordinates = wined3d_desc.desktop_rect;
320 desc->AttachedToDesktop = wined3d_desc.attached_to_desktop;
321 desc->Rotation = rotation;
322 desc->Monitor = wined3d_desc.monitor;
324 return S_OK;
327 static HRESULT STDMETHODCALLTYPE dxgi_output_GetDisplayModeList(IDXGIOutput6 *iface,
328 DXGI_FORMAT format, UINT flags, UINT *mode_count, DXGI_MODE_DESC *modes)
330 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
332 FIXME("iface %p, format %s, flags %#x, mode_count %p, modes %p partial stub!\n",
333 iface, debug_dxgi_format(format), flags, mode_count, modes);
335 return dxgi_output_get_display_mode_list(output,
336 format, mode_count, modes, DXGI_MODE_STRUCT_VERSION_0);
339 static HRESULT STDMETHODCALLTYPE dxgi_output_FindClosestMatchingMode(IDXGIOutput6 *iface,
340 const DXGI_MODE_DESC *mode, DXGI_MODE_DESC *closest_match, IUnknown *device)
342 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
343 struct wined3d_display_mode wined3d_mode;
344 HRESULT hr;
346 TRACE("iface %p, mode %p, closest_match %p, device %p.\n",
347 iface, mode, closest_match, device);
349 TRACE("Mode: %s.\n", debug_dxgi_mode(mode));
351 wined3d_display_mode_from_dxgi(&wined3d_mode, mode);
352 hr = dxgi_output_find_closest_matching_mode(output, &wined3d_mode, device);
353 if (SUCCEEDED(hr))
355 dxgi_mode_from_wined3d(closest_match, &wined3d_mode);
356 TRACE("Returning %s.\n", debug_dxgi_mode(closest_match));
359 return hr;
362 static HRESULT STDMETHODCALLTYPE dxgi_output_WaitForVBlank(IDXGIOutput6 *iface)
364 static BOOL once = FALSE;
366 if (!once++)
367 FIXME("iface %p stub!\n", iface);
368 else
369 TRACE("iface %p stub!\n", iface);
371 return E_NOTIMPL;
374 static HRESULT STDMETHODCALLTYPE dxgi_output_TakeOwnership(IDXGIOutput6 *iface, IUnknown *device, BOOL exclusive)
376 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
377 HRESULT hr;
379 TRACE("iface %p, device %p, exclusive %d.\n", iface, device, exclusive);
381 if (!device)
382 return DXGI_ERROR_INVALID_CALL;
384 wined3d_mutex_lock();
385 hr = wined3d_output_take_ownership(output->wined3d_output, exclusive);
386 wined3d_mutex_unlock();
388 return hr;
391 static void STDMETHODCALLTYPE dxgi_output_ReleaseOwnership(IDXGIOutput6 *iface)
393 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
395 TRACE("iface %p.\n", iface);
397 wined3d_mutex_lock();
398 wined3d_output_release_ownership(output->wined3d_output);
399 wined3d_mutex_unlock();
402 static HRESULT STDMETHODCALLTYPE dxgi_output_GetGammaControlCapabilities(IDXGIOutput6 *iface,
403 DXGI_GAMMA_CONTROL_CAPABILITIES *gamma_caps)
405 unsigned int i;
407 TRACE("iface %p, gamma_caps %p.\n", iface, gamma_caps);
409 if (!gamma_caps)
410 return E_INVALIDARG;
412 gamma_caps->ScaleAndOffsetSupported = FALSE;
413 gamma_caps->MaxConvertedValue = 1.0f;
414 gamma_caps->MinConvertedValue = 0.0f;
415 gamma_caps->NumGammaControlPoints = 256;
417 for (i = 0; i < gamma_caps->NumGammaControlPoints; ++i)
418 gamma_caps->ControlPointPositions[i] = i / 255.0f;
420 return S_OK;
423 static HRESULT STDMETHODCALLTYPE dxgi_output_SetGammaControl(IDXGIOutput6 *iface,
424 const DXGI_GAMMA_CONTROL *gamma_control)
426 FIXME("iface %p, gamma_control %p stub!\n", iface, gamma_control);
428 return S_OK;
431 static HRESULT STDMETHODCALLTYPE dxgi_output_GetGammaControl(IDXGIOutput6 *iface,
432 DXGI_GAMMA_CONTROL *gamma_control)
434 FIXME("iface %p, gamma_control %p stub!\n", iface, gamma_control);
436 return E_NOTIMPL;
439 static HRESULT STDMETHODCALLTYPE dxgi_output_SetDisplaySurface(IDXGIOutput6 *iface, IDXGISurface *surface)
441 FIXME("iface %p, surface %p stub!\n", iface, surface);
443 return E_NOTIMPL;
446 static HRESULT STDMETHODCALLTYPE dxgi_output_GetDisplaySurfaceData(IDXGIOutput6 *iface, IDXGISurface *surface)
448 FIXME("iface %p, surface %p stub!\n", iface, surface);
450 return E_NOTIMPL;
453 static HRESULT STDMETHODCALLTYPE dxgi_output_GetFrameStatistics(IDXGIOutput6 *iface, DXGI_FRAME_STATISTICS *stats)
455 FIXME("iface %p, stats %p stub!\n", iface, stats);
457 return E_NOTIMPL;
460 /* IDXGIOutput1 methods */
462 static HRESULT STDMETHODCALLTYPE dxgi_output_GetDisplayModeList1(IDXGIOutput6 *iface,
463 DXGI_FORMAT format, UINT flags, UINT *mode_count, DXGI_MODE_DESC1 *modes)
465 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
467 FIXME("iface %p, format %s, flags %#x, mode_count %p, modes %p partial stub!\n",
468 iface, debug_dxgi_format(format), flags, mode_count, modes);
470 return dxgi_output_get_display_mode_list(output,
471 format, mode_count, modes, DXGI_MODE_STRUCT_VERSION_1);
474 static HRESULT STDMETHODCALLTYPE dxgi_output_FindClosestMatchingMode1(IDXGIOutput6 *iface,
475 const DXGI_MODE_DESC1 *mode, DXGI_MODE_DESC1 *closest_match, IUnknown *device)
477 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
478 struct wined3d_display_mode wined3d_mode;
479 HRESULT hr;
481 TRACE("iface %p, mode %p, closest_match %p, device %p.\n",
482 iface, mode, closest_match, device);
484 TRACE("Mode: %s.\n", debug_dxgi_mode1(mode));
486 wined3d_display_mode_from_dxgi1(&wined3d_mode, mode);
487 hr = dxgi_output_find_closest_matching_mode(output, &wined3d_mode, device);
488 if (SUCCEEDED(hr))
490 dxgi_mode1_from_wined3d(closest_match, &wined3d_mode);
491 TRACE("Returning %s.\n", debug_dxgi_mode1(closest_match));
494 return hr;
497 static HRESULT STDMETHODCALLTYPE dxgi_output_GetDisplaySurfaceData1(IDXGIOutput6 *iface,
498 IDXGIResource *resource)
500 FIXME("iface %p, resource %p stub!\n", iface, resource);
502 return E_NOTIMPL;
505 static HRESULT STDMETHODCALLTYPE dxgi_output_DuplicateOutput(IDXGIOutput6 *iface,
506 IUnknown *device, IDXGIOutputDuplication **output_duplication)
508 FIXME("iface %p, device %p, output_duplication %p stub!\n", iface, device, output_duplication);
510 return E_NOTIMPL;
513 /* IDXGIOutput2 methods */
515 static BOOL STDMETHODCALLTYPE dxgi_output_SupportsOverlays(IDXGIOutput6 *iface)
517 FIXME("iface %p stub!\n", iface);
519 return FALSE;
522 /* IDXGIOutput3 methods */
524 static HRESULT STDMETHODCALLTYPE dxgi_output_CheckOverlaySupport(IDXGIOutput6 *iface,
525 DXGI_FORMAT format, IUnknown *device, UINT *flags)
527 FIXME("iface %p, format %#x, device %p, flags %p stub!\n", iface, format, device, flags);
529 return E_NOTIMPL;
532 /* IDXGIOutput4 methods */
534 static HRESULT STDMETHODCALLTYPE dxgi_output_CheckOverlayColorSpaceSupport(IDXGIOutput6 *iface,
535 DXGI_FORMAT format, DXGI_COLOR_SPACE_TYPE color_space, IUnknown *device, UINT *flags)
537 FIXME("iface %p, format %#x, color_space %#x, device %p, flags %p stub!\n",
538 iface, format, color_space, device, flags);
540 return E_NOTIMPL;
543 /* IDXGIOutput5 methods */
545 static HRESULT STDMETHODCALLTYPE dxgi_output_DuplicateOutput1(IDXGIOutput6 *iface,
546 IUnknown *device, UINT flags, UINT format_count, const DXGI_FORMAT *formats,
547 IDXGIOutputDuplication **output_duplication)
549 FIXME("iface %p, device %p, flags %#x, format_count %u, formats %p, "
550 "output_duplication %p stub!\n", iface, device, flags, format_count,
551 formats, output_duplication);
553 return E_NOTIMPL;
556 /* IDXGIOutput6 methods */
558 static HRESULT STDMETHODCALLTYPE dxgi_output_GetDesc1(IDXGIOutput6 *iface,
559 DXGI_OUTPUT_DESC1 *desc)
561 struct dxgi_output *output = impl_from_IDXGIOutput6(iface);
562 struct wined3d_output_desc wined3d_desc;
563 enum wined3d_display_rotation rotation;
564 struct wined3d_display_mode mode;
565 HRESULT hr;
567 FIXME("iface %p, desc %p semi-stub!\n", iface, desc);
569 if (!desc)
570 return E_INVALIDARG;
572 wined3d_mutex_lock();
573 hr = wined3d_output_get_desc(output->wined3d_output, &wined3d_desc);
574 if (FAILED(hr))
576 WARN("Failed to get output desc, hr %#x.\n", hr);
577 wined3d_mutex_unlock();
578 return hr;
581 hr = wined3d_output_get_display_mode(output->wined3d_output, &mode, &rotation);
582 if (FAILED(hr))
584 WARN("Failed to get output display mode, hr %#x.\n", hr);
585 wined3d_mutex_unlock();
586 return hr;
588 wined3d_mutex_unlock();
590 if (FAILED(hr))
592 WARN("Failed to get output desc, hr %#x.\n", hr);
593 return hr;
596 memcpy(desc->DeviceName, wined3d_desc.device_name, sizeof(desc->DeviceName));
597 desc->DesktopCoordinates = wined3d_desc.desktop_rect;
598 desc->AttachedToDesktop = wined3d_desc.attached_to_desktop;
599 desc->Rotation = rotation;
600 desc->Monitor = wined3d_desc.monitor;
602 /* FIXME: fill this from monitor EDID */
603 desc->BitsPerColor = 0;
604 desc->ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
605 desc->RedPrimary[0] = 0.f;
606 desc->RedPrimary[1] = 0.f;
607 desc->GreenPrimary[0] = 0.f;
608 desc->GreenPrimary[1] = 0.f;
609 desc->BluePrimary[0] = 0.f;
610 desc->BluePrimary[1] = 0.f;
611 desc->WhitePoint[0] = 0.f;
612 desc->WhitePoint[1] = 0.f;
613 desc->MinLuminance = 0.f;
614 desc->MaxLuminance = 0.f;
615 desc->MaxFullFrameLuminance = 0.f;
617 return S_OK;
620 static HRESULT STDMETHODCALLTYPE dxgi_output_CheckHardwareCompositionSupport(IDXGIOutput6 *iface,
621 UINT *flags)
623 FIXME("iface %p, flags %p stub!\n", iface, flags);
625 return E_NOTIMPL;
628 static const struct IDXGIOutput6Vtbl dxgi_output_vtbl =
630 dxgi_output_QueryInterface,
631 dxgi_output_AddRef,
632 dxgi_output_Release,
633 /* IDXGIObject methods */
634 dxgi_output_SetPrivateData,
635 dxgi_output_SetPrivateDataInterface,
636 dxgi_output_GetPrivateData,
637 dxgi_output_GetParent,
638 /* IDXGIOutput methods */
639 dxgi_output_GetDesc,
640 dxgi_output_GetDisplayModeList,
641 dxgi_output_FindClosestMatchingMode,
642 dxgi_output_WaitForVBlank,
643 dxgi_output_TakeOwnership,
644 dxgi_output_ReleaseOwnership,
645 dxgi_output_GetGammaControlCapabilities,
646 dxgi_output_SetGammaControl,
647 dxgi_output_GetGammaControl,
648 dxgi_output_SetDisplaySurface,
649 dxgi_output_GetDisplaySurfaceData,
650 dxgi_output_GetFrameStatistics,
651 /* IDXGIOutput1 methods */
652 dxgi_output_GetDisplayModeList1,
653 dxgi_output_FindClosestMatchingMode1,
654 dxgi_output_GetDisplaySurfaceData1,
655 dxgi_output_DuplicateOutput,
656 /* IDXGIOutput2 methods */
657 dxgi_output_SupportsOverlays,
658 /* IDXGIOutput3 methods */
659 dxgi_output_CheckOverlaySupport,
660 /* IDXGIOutput4 methods */
661 dxgi_output_CheckOverlayColorSpaceSupport,
662 /* IDXGIOutput5 methods */
663 dxgi_output_DuplicateOutput1,
664 /* IDXGIOutput6 methods */
665 dxgi_output_GetDesc1,
666 dxgi_output_CheckHardwareCompositionSupport,
669 struct dxgi_output *unsafe_impl_from_IDXGIOutput(IDXGIOutput *iface)
671 if (!iface)
672 return NULL;
673 assert(iface->lpVtbl == (IDXGIOutputVtbl *)&dxgi_output_vtbl);
674 return CONTAINING_RECORD(iface, struct dxgi_output, IDXGIOutput6_iface);
677 static void dxgi_output_init(struct dxgi_output *output, unsigned int output_idx,
678 struct dxgi_adapter *adapter)
680 output->IDXGIOutput6_iface.lpVtbl = &dxgi_output_vtbl;
681 output->refcount = 1;
682 output->wined3d_output = wined3d_adapter_get_output(adapter->wined3d_adapter, output_idx);
683 wined3d_private_store_init(&output->private_store);
684 output->adapter = adapter;
685 IWineDXGIAdapter_AddRef(&output->adapter->IWineDXGIAdapter_iface);
688 HRESULT dxgi_output_create(struct dxgi_adapter *adapter, unsigned int output_idx,
689 struct dxgi_output **output)
691 if (!(*output = heap_alloc_zero(sizeof(**output))))
692 return E_OUTOFMEMORY;
694 dxgi_output_init(*output, output_idx, adapter);
695 return S_OK;