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
21 #include "wine/port.h"
23 #include "dxgi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dxgi
);
27 static inline struct dxgi_swapchain
*impl_from_IDXGISwapChain1(IDXGISwapChain1
*iface
)
29 return CONTAINING_RECORD(iface
, struct dxgi_swapchain
, IDXGISwapChain1_iface
);
32 /* IUnknown methods */
34 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_QueryInterface(IDXGISwapChain1
*iface
, REFIID riid
, void **object
)
36 TRACE("iface %p, riid %s, object %p\n", iface
, debugstr_guid(riid
), object
);
38 if (IsEqualGUID(riid
, &IID_IUnknown
)
39 || IsEqualGUID(riid
, &IID_IDXGIObject
)
40 || IsEqualGUID(riid
, &IID_IDXGIDeviceSubObject
)
41 || IsEqualGUID(riid
, &IID_IDXGISwapChain
)
42 || IsEqualGUID(riid
, &IID_IDXGISwapChain1
))
44 IUnknown_AddRef(iface
);
49 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid
));
55 static ULONG STDMETHODCALLTYPE
dxgi_swapchain_AddRef(IDXGISwapChain1
*iface
)
57 struct dxgi_swapchain
*This
= impl_from_IDXGISwapChain1(iface
);
58 ULONG refcount
= InterlockedIncrement(&This
->refcount
);
60 TRACE("%p increasing refcount to %u\n", This
, refcount
);
65 wined3d_swapchain_incref(This
->wined3d_swapchain
);
66 wined3d_mutex_unlock();
72 static ULONG STDMETHODCALLTYPE
dxgi_swapchain_Release(IDXGISwapChain1
*iface
)
74 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
75 ULONG refcount
= InterlockedDecrement(&swapchain
->refcount
);
77 TRACE("%p decreasing refcount to %u.\n", swapchain
, refcount
);
81 IWineDXGIDevice
*device
= swapchain
->device
;
82 if (swapchain
->target
)
84 WARN("Releasing fullscreen swapchain.\n");
85 IDXGIOutput_Release(swapchain
->target
);
87 if (swapchain
->factory
)
88 IDXGIFactory_Release(swapchain
->factory
);
90 wined3d_swapchain_decref(swapchain
->wined3d_swapchain
);
91 wined3d_mutex_unlock();
93 IWineDXGIDevice_Release(device
);
99 /* IDXGIObject methods */
101 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_SetPrivateData(IDXGISwapChain1
*iface
,
102 REFGUID guid
, UINT data_size
, const void *data
)
104 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
106 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
108 return dxgi_set_private_data(&swapchain
->private_store
, guid
, data_size
, data
);
111 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_SetPrivateDataInterface(IDXGISwapChain1
*iface
,
112 REFGUID guid
, const IUnknown
*object
)
114 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
116 TRACE("iface %p, guid %s, object %p.\n", iface
, debugstr_guid(guid
), object
);
118 return dxgi_set_private_data_interface(&swapchain
->private_store
, guid
, object
);
121 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetPrivateData(IDXGISwapChain1
*iface
,
122 REFGUID guid
, UINT
*data_size
, void *data
)
124 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
126 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
128 return dxgi_get_private_data(&swapchain
->private_store
, guid
, data_size
, data
);
131 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetParent(IDXGISwapChain1
*iface
, REFIID riid
, void **parent
)
133 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
135 TRACE("iface %p, riid %s, parent %p.\n", iface
, debugstr_guid(riid
), parent
);
137 if (!swapchain
->factory
)
139 ERR("Implicit swapchain does not store reference to parent.\n");
141 return E_NOINTERFACE
;
144 return IDXGIFactory_QueryInterface(swapchain
->factory
, riid
, parent
);
147 /* IDXGIDeviceSubObject methods */
149 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetDevice(IDXGISwapChain1
*iface
, REFIID riid
, void **device
)
151 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
153 TRACE("iface %p, riid %s, device %p.\n", iface
, debugstr_guid(riid
), device
);
155 if (!swapchain
->device
)
157 ERR("Implicit swapchain does not store reference to device.\n");
159 return E_NOINTERFACE
;
162 return IWineDXGIDevice_QueryInterface(swapchain
->device
, riid
, device
);
165 /* IDXGISwapChain1 methods */
167 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_Present(IDXGISwapChain1
*iface
, UINT sync_interval
, UINT flags
)
169 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
171 TRACE("iface %p, sync_interval %u, flags %#x.\n", iface
, sync_interval
, flags
);
173 return IDXGISwapChain1_Present1(&swapchain
->IDXGISwapChain1_iface
, sync_interval
, flags
, NULL
);
176 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetBuffer(IDXGISwapChain1
*iface
,
177 UINT buffer_idx
, REFIID riid
, void **surface
)
179 struct dxgi_swapchain
*This
= impl_from_IDXGISwapChain1(iface
);
180 struct wined3d_texture
*texture
;
184 TRACE("iface %p, buffer_idx %u, riid %s, surface %p\n",
185 iface
, buffer_idx
, debugstr_guid(riid
), surface
);
187 wined3d_mutex_lock();
189 if (!(texture
= wined3d_swapchain_get_back_buffer(This
->wined3d_swapchain
, buffer_idx
)))
191 wined3d_mutex_unlock();
192 return DXGI_ERROR_INVALID_CALL
;
195 parent
= wined3d_texture_get_parent(texture
);
196 hr
= IUnknown_QueryInterface(parent
, riid
, surface
);
197 wined3d_mutex_unlock();
202 static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH
dxgi_swapchain_SetFullscreenState(IDXGISwapChain1
*iface
,
203 BOOL fullscreen
, IDXGIOutput
*target
)
205 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
206 struct wined3d_swapchain_desc swapchain_desc
;
209 TRACE("iface %p, fullscreen %#x, target %p.\n", iface
, fullscreen
, target
);
211 if (!fullscreen
&& target
)
213 WARN("Invalid call.\n");
214 return DXGI_ERROR_INVALID_CALL
;
221 IDXGIOutput_AddRef(target
);
223 else if (FAILED(hr
= IDXGISwapChain1_GetContainingOutput(iface
, &target
)))
225 WARN("Failed to get default target output for swapchain, hr %#x.\n", hr
);
230 wined3d_mutex_lock();
231 wined3d_swapchain_get_desc(swapchain
->wined3d_swapchain
, &swapchain_desc
);
232 swapchain_desc
.windowed
= !fullscreen
;
233 hr
= wined3d_swapchain_set_fullscreen(swapchain
->wined3d_swapchain
, &swapchain_desc
, NULL
);
234 wined3d_mutex_unlock();
238 swapchain
->fullscreen
= fullscreen
;
239 if (swapchain
->target
)
240 IDXGIOutput_Release(swapchain
->target
);
241 swapchain
->target
= target
;
245 IDXGIOutput_Release(target
);
251 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetFullscreenState(IDXGISwapChain1
*iface
,
252 BOOL
*fullscreen
, IDXGIOutput
**target
)
254 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
256 TRACE("iface %p, fullscreen %p, target %p.\n", iface
, fullscreen
, target
);
259 *fullscreen
= swapchain
->fullscreen
;
263 *target
= swapchain
->target
;
265 IDXGIOutput_AddRef(*target
);
271 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetDesc(IDXGISwapChain1
*iface
, DXGI_SWAP_CHAIN_DESC
*desc
)
273 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
274 struct wined3d_swapchain_desc wined3d_desc
;
276 TRACE("iface %p, desc %p.\n", iface
, desc
);
280 WARN("Invalid pointer.\n");
284 wined3d_mutex_lock();
285 wined3d_swapchain_get_desc(swapchain
->wined3d_swapchain
, &wined3d_desc
);
286 wined3d_mutex_unlock();
288 FIXME("Ignoring ScanlineOrdering, Scaling and SwapEffect.\n");
290 desc
->BufferDesc
.Width
= wined3d_desc
.backbuffer_width
;
291 desc
->BufferDesc
.Height
= wined3d_desc
.backbuffer_height
;
292 desc
->BufferDesc
.RefreshRate
.Numerator
= wined3d_desc
.refresh_rate
;
293 desc
->BufferDesc
.RefreshRate
.Denominator
= 1;
294 desc
->BufferDesc
.Format
= dxgi_format_from_wined3dformat(wined3d_desc
.backbuffer_format
);
295 desc
->BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
296 desc
->BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
297 dxgi_sample_desc_from_wined3d(&desc
->SampleDesc
,
298 wined3d_desc
.multisample_type
, wined3d_desc
.multisample_quality
);
299 desc
->BufferUsage
= dxgi_usage_from_wined3d_usage(wined3d_desc
.backbuffer_usage
);
300 desc
->BufferCount
= wined3d_desc
.backbuffer_count
;
301 desc
->OutputWindow
= wined3d_desc
.device_window
;
302 desc
->Windowed
= wined3d_desc
.windowed
;
303 desc
->SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
304 desc
->Flags
= dxgi_swapchain_flags_from_wined3d(wined3d_desc
.flags
);
309 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_ResizeBuffers(IDXGISwapChain1
*iface
,
310 UINT buffer_count
, UINT width
, UINT height
, DXGI_FORMAT format
, UINT flags
)
312 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
313 struct wined3d_swapchain_desc wined3d_desc
;
314 struct wined3d_texture
*texture
;
319 TRACE("iface %p, buffer_count %u, width %u, height %u, format %s, flags %#x.\n",
320 iface
, buffer_count
, width
, height
, debug_dxgi_format(format
), flags
);
323 FIXME("Ignoring flags %#x.\n", flags
);
325 wined3d_mutex_lock();
326 wined3d_swapchain_get_desc(swapchain
->wined3d_swapchain
, &wined3d_desc
);
327 for (i
= 0; i
< wined3d_desc
.backbuffer_count
; ++i
)
329 texture
= wined3d_swapchain_get_back_buffer(swapchain
->wined3d_swapchain
, i
);
330 parent
= wined3d_texture_get_parent(texture
);
331 IUnknown_AddRef(parent
);
332 if (IUnknown_Release(parent
))
334 wined3d_mutex_unlock();
335 return DXGI_ERROR_INVALID_CALL
;
338 if (format
!= DXGI_FORMAT_UNKNOWN
)
339 wined3d_desc
.backbuffer_format
= wined3dformat_from_dxgi_format(format
);
340 hr
= wined3d_swapchain_resize_buffers(swapchain
->wined3d_swapchain
, buffer_count
, width
, height
,
341 wined3d_desc
.backbuffer_format
, wined3d_desc
.multisample_type
, wined3d_desc
.multisample_quality
);
342 wined3d_mutex_unlock();
347 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_ResizeTarget(IDXGISwapChain1
*iface
,
348 const DXGI_MODE_DESC
*target_mode_desc
)
350 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
351 struct wined3d_display_mode mode
;
354 TRACE("iface %p, target_mode_desc %p.\n", iface
, target_mode_desc
);
356 if (!target_mode_desc
)
358 WARN("Invalid pointer.\n");
359 return DXGI_ERROR_INVALID_CALL
;
362 TRACE("Mode: %s.\n", debug_dxgi_mode(target_mode_desc
));
364 if (target_mode_desc
->Scaling
)
365 FIXME("Ignoring scaling %#x.\n", target_mode_desc
->Scaling
);
367 wined3d_display_mode_from_dxgi(&mode
, target_mode_desc
);
369 wined3d_mutex_lock();
370 hr
= wined3d_swapchain_resize_target(swapchain
->wined3d_swapchain
, &mode
);
371 wined3d_mutex_unlock();
376 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetContainingOutput(IDXGISwapChain1
*iface
, IDXGIOutput
**output
)
378 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
379 IDXGIAdapter
*adapter
;
383 TRACE("iface %p, output %p.\n", iface
, output
);
385 if (swapchain
->target
)
387 IDXGIOutput_AddRef(*output
= swapchain
->target
);
391 if (FAILED(hr
= dxgi_swapchain_GetDevice(iface
, &IID_IDXGIDevice
, (void **)&device
)))
394 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
395 IDXGIDevice_Release(device
);
398 WARN("GetAdapter failed, hr %#x.\n", hr
);
402 if (SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, 1, output
)))
404 FIXME("Adapter has got multiple outputs, returning the first one.\n");
405 IDXGIOutput_Release(*output
);
408 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, output
);
409 IDXGIAdapter_Release(adapter
);
413 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetFrameStatistics(IDXGISwapChain1
*iface
,
414 DXGI_FRAME_STATISTICS
*stats
)
416 FIXME("iface %p, stats %p stub!\n", iface
, stats
);
421 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetLastPresentCount(IDXGISwapChain1
*iface
,
422 UINT
*last_present_count
)
424 FIXME("iface %p, last_present_count %p stub!\n", iface
, last_present_count
);
429 /* IDXGISwapChain1 methods */
431 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetDesc1(IDXGISwapChain1
*iface
, DXGI_SWAP_CHAIN_DESC1
*desc
)
433 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
434 struct wined3d_swapchain_desc wined3d_desc
;
436 TRACE("iface %p, desc %p.\n", iface
, desc
);
440 WARN("Invalid pointer.\n");
444 wined3d_mutex_lock();
445 wined3d_swapchain_get_desc(swapchain
->wined3d_swapchain
, &wined3d_desc
);
446 wined3d_mutex_unlock();
448 FIXME("Ignoring Stereo, Scaling, SwapEffect and AlphaMode.\n");
450 desc
->Width
= wined3d_desc
.backbuffer_width
;
451 desc
->Height
= wined3d_desc
.backbuffer_height
;
452 desc
->Format
= dxgi_format_from_wined3dformat(wined3d_desc
.backbuffer_format
);
453 desc
->Stereo
= FALSE
;
454 dxgi_sample_desc_from_wined3d(&desc
->SampleDesc
,
455 wined3d_desc
.multisample_type
, wined3d_desc
.multisample_quality
);
456 desc
->BufferUsage
= dxgi_usage_from_wined3d_usage(wined3d_desc
.backbuffer_usage
);
457 desc
->BufferCount
= wined3d_desc
.backbuffer_count
;
458 desc
->Scaling
= DXGI_SCALING_STRETCH
;
459 desc
->SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
460 desc
->AlphaMode
= DXGI_ALPHA_MODE_IGNORE
;
461 desc
->Flags
= dxgi_swapchain_flags_from_wined3d(wined3d_desc
.flags
);
466 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetFullscreenDesc(IDXGISwapChain1
*iface
,
467 DXGI_SWAP_CHAIN_FULLSCREEN_DESC
*desc
)
469 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
470 struct wined3d_swapchain_desc wined3d_desc
;
472 TRACE("iface %p, desc %p.\n", iface
, desc
);
476 WARN("Invalid pointer.\n");
480 wined3d_mutex_lock();
481 wined3d_swapchain_get_desc(swapchain
->wined3d_swapchain
, &wined3d_desc
);
482 wined3d_mutex_unlock();
484 FIXME("Ignoring ScanlineOrdering and Scaling.\n");
486 desc
->RefreshRate
.Numerator
= wined3d_desc
.refresh_rate
;
487 desc
->RefreshRate
.Denominator
= 1;
488 desc
->ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
489 desc
->Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
490 desc
->Windowed
= wined3d_desc
.windowed
;
495 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetHwnd(IDXGISwapChain1
*iface
, HWND
*hwnd
)
497 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
498 struct wined3d_swapchain_desc wined3d_desc
;
500 TRACE("iface %p, hwnd %p.\n", iface
, hwnd
);
504 WARN("Invalid pointer.\n");
505 return DXGI_ERROR_INVALID_CALL
;
508 wined3d_mutex_lock();
509 wined3d_swapchain_get_desc(swapchain
->wined3d_swapchain
, &wined3d_desc
);
510 wined3d_mutex_unlock();
512 *hwnd
= wined3d_desc
.device_window
;
516 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetCoreWindow(IDXGISwapChain1
*iface
,
517 REFIID iid
, void **core_window
)
519 FIXME("iface %p, iid %s, core_window %p stub!\n", iface
, debugstr_guid(iid
), core_window
);
524 return DXGI_ERROR_INVALID_CALL
;
527 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_Present1(IDXGISwapChain1
*iface
,
528 UINT sync_interval
, UINT flags
, const DXGI_PRESENT_PARAMETERS
*present_parameters
)
530 struct dxgi_swapchain
*swapchain
= impl_from_IDXGISwapChain1(iface
);
533 TRACE("iface %p, sync_interval %u, flags %#x, present_parameters %p.\n",
534 iface
, sync_interval
, flags
, present_parameters
);
536 if (flags
& ~DXGI_PRESENT_TEST
)
537 FIXME("Unimplemented flags %#x.\n", flags
);
538 if (flags
& DXGI_PRESENT_TEST
)
540 WARN("Returning S_OK for DXGI_PRESENT_TEST.\n");
545 FIXME("Unimplemented sync interval %u.\n", sync_interval
);
546 if (present_parameters
)
547 FIXME("Ignored present parameters %p.\n", present_parameters
);
549 wined3d_mutex_lock();
550 hr
= wined3d_swapchain_present(swapchain
->wined3d_swapchain
, NULL
, NULL
, NULL
, 0);
551 wined3d_mutex_unlock();
556 static BOOL STDMETHODCALLTYPE
dxgi_swapchain_IsTemporaryMonoSupported(IDXGISwapChain1
*iface
)
558 FIXME("iface %p stub!\n", iface
);
563 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetRestrictToOutput(IDXGISwapChain1
*iface
, IDXGIOutput
**output
)
565 FIXME("iface %p, output %p stub!\n", iface
, output
);
569 WARN("Invalid pointer.\n");
577 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_SetBackgroundColor(IDXGISwapChain1
*iface
, const DXGI_RGBA
*color
)
579 FIXME("iface %p, color %p stub!\n", iface
, color
);
584 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetBackgroundColor(IDXGISwapChain1
*iface
, DXGI_RGBA
*color
)
586 FIXME("iface %p, color %p stub!\n", iface
, color
);
591 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_SetRotation(IDXGISwapChain1
*iface
, DXGI_MODE_ROTATION rotation
)
593 FIXME("iface %p, rotation %#x stub!\n", iface
, rotation
);
598 static HRESULT STDMETHODCALLTYPE
dxgi_swapchain_GetRotation(IDXGISwapChain1
*iface
, DXGI_MODE_ROTATION
*rotation
)
600 FIXME("iface %p, rotation %p stub!\n", iface
, rotation
);
605 static const struct IDXGISwapChain1Vtbl dxgi_swapchain_vtbl
=
607 /* IUnknown methods */
608 dxgi_swapchain_QueryInterface
,
609 dxgi_swapchain_AddRef
,
610 dxgi_swapchain_Release
,
611 /* IDXGIObject methods */
612 dxgi_swapchain_SetPrivateData
,
613 dxgi_swapchain_SetPrivateDataInterface
,
614 dxgi_swapchain_GetPrivateData
,
615 dxgi_swapchain_GetParent
,
616 /* IDXGIDeviceSubObject methods */
617 dxgi_swapchain_GetDevice
,
618 /* IDXGISwapChain methods */
619 dxgi_swapchain_Present
,
620 dxgi_swapchain_GetBuffer
,
621 dxgi_swapchain_SetFullscreenState
,
622 dxgi_swapchain_GetFullscreenState
,
623 dxgi_swapchain_GetDesc
,
624 dxgi_swapchain_ResizeBuffers
,
625 dxgi_swapchain_ResizeTarget
,
626 dxgi_swapchain_GetContainingOutput
,
627 dxgi_swapchain_GetFrameStatistics
,
628 dxgi_swapchain_GetLastPresentCount
,
629 /* IDXGISwapChain1 methods */
630 dxgi_swapchain_GetDesc1
,
631 dxgi_swapchain_GetFullscreenDesc
,
632 dxgi_swapchain_GetHwnd
,
633 dxgi_swapchain_GetCoreWindow
,
634 dxgi_swapchain_Present1
,
635 dxgi_swapchain_IsTemporaryMonoSupported
,
636 dxgi_swapchain_GetRestrictToOutput
,
637 dxgi_swapchain_SetBackgroundColor
,
638 dxgi_swapchain_GetBackgroundColor
,
639 dxgi_swapchain_SetRotation
,
640 dxgi_swapchain_GetRotation
,
643 static void STDMETHODCALLTYPE
dxgi_swapchain_wined3d_object_released(void *parent
)
645 struct dxgi_swapchain
*swapchain
= parent
;
647 wined3d_private_store_cleanup(&swapchain
->private_store
);
651 static const struct wined3d_parent_ops dxgi_swapchain_wined3d_parent_ops
=
653 dxgi_swapchain_wined3d_object_released
,
656 HRESULT
dxgi_swapchain_init(struct dxgi_swapchain
*swapchain
, struct dxgi_device
*device
,
657 struct wined3d_swapchain_desc
*desc
, BOOL implicit
)
662 * A reference to the implicit swapchain is held by the wined3d device.
663 * In order to avoid circular references we do not keep a reference
664 * to the device in the implicit swapchain.
668 if (FAILED(hr
= IWineDXGIAdapter_GetParent(device
->adapter
, &IID_IDXGIFactory
,
669 (void **)&swapchain
->factory
)))
671 WARN("Failed to get adapter parent, hr %#x.\n", hr
);
674 IWineDXGIDevice_AddRef(swapchain
->device
= &device
->IWineDXGIDevice_iface
);
678 swapchain
->device
= NULL
;
679 swapchain
->factory
= NULL
;
682 swapchain
->IDXGISwapChain1_iface
.lpVtbl
= &dxgi_swapchain_vtbl
;
683 swapchain
->refcount
= 1;
684 wined3d_mutex_lock();
685 wined3d_private_store_init(&swapchain
->private_store
);
687 if (!desc
->windowed
&& (!desc
->backbuffer_width
|| !desc
->backbuffer_height
))
688 FIXME("Fullscreen swapchain with back buffer width/height equal to 0 not supported properly.\n");
690 swapchain
->fullscreen
= !desc
->windowed
;
691 desc
->windowed
= TRUE
;
692 if (FAILED(hr
= wined3d_swapchain_create(device
->wined3d_device
, desc
, swapchain
,
693 &dxgi_swapchain_wined3d_parent_ops
, &swapchain
->wined3d_swapchain
)))
695 WARN("Failed to create wined3d swapchain, hr %#x.\n", hr
);
699 swapchain
->target
= NULL
;
700 if (swapchain
->fullscreen
)
702 desc
->windowed
= FALSE
;
703 if (FAILED(hr
= wined3d_swapchain_set_fullscreen(swapchain
->wined3d_swapchain
,
706 WARN("Failed to set fullscreen state, hr %#x.\n", hr
);
707 wined3d_swapchain_decref(swapchain
->wined3d_swapchain
);
711 if (FAILED(hr
= IDXGISwapChain1_GetContainingOutput(&swapchain
->IDXGISwapChain1_iface
,
712 &swapchain
->target
)))
714 WARN("Failed to get target output for fullscreen swapchain, hr %#x.\n", hr
);
715 wined3d_swapchain_decref(swapchain
->wined3d_swapchain
);
719 wined3d_mutex_unlock();
724 wined3d_private_store_cleanup(&swapchain
->private_store
);
725 wined3d_mutex_unlock();
726 if (swapchain
->factory
)
727 IDXGIFactory_Release(swapchain
->factory
);
728 if (swapchain
->device
)
729 IWineDXGIDevice_Release(swapchain
->device
);