d3d11window: Use CreateSwapChainForHwnd if available

That's recommended way from MS and CreateSwapChainForHwnd supports
more options than CreateSwapChain
This commit is contained in:
Seungha Yang 2019-12-18 14:23:03 +09:00
parent 9fd0b62f2d
commit 32d618c677
3 changed files with 135 additions and 25 deletions

View file

@ -783,6 +783,72 @@ gst_d3d11_device_create_swap_chain (GstD3D11Device * device,
return data.swap_chain;
}
#if (DXGI_HEADER_VERSION >= 2)
typedef struct
{
IDXGISwapChain1 *swap_chain;
HWND hwnd;
const DXGI_SWAP_CHAIN_DESC1 *desc;
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc;
IDXGIOutput *output;
} CreateSwapChainForHwndData;
static void
gst_d3d11_device_create_swap_chain_for_hwnd_internal (GstD3D11Device * device,
CreateSwapChainForHwndData * data)
{
GstD3D11DevicePrivate *priv = device->priv;
HRESULT hr;
hr = IDXGIFactory2_CreateSwapChainForHwnd ((IDXGIFactory2 *) priv->factory,
(IUnknown *) priv->device, data->hwnd, data->desc, data->fullscreen_desc,
data->output, &data->swap_chain);
if (!gst_d3d11_result (hr)) {
GST_ERROR_OBJECT (device, "Cannot create SwapChain Object: 0x%x",
(guint) hr);
data->swap_chain = NULL;
}
}
/**
* gst_d3d11_device_create_swap_chain_for_hwnd:
* @device: a #GstD3D11Device
* @hwnd: HWND handle
* @desc: a DXGI_SWAP_CHAIN_DESC1 structure for swapchain
* @fullscreen_desc: (nullable): a DXGI_SWAP_CHAIN_FULLSCREEN_DESC
* structure for swapchain
* @output: (nullable): a IDXGIOutput interface for the output to restrict content to
*
* Create a IDXGISwapChain1 object. Caller must release returned swap chain object
* via IDXGISwapChain1_Release()
*
* Returns: (transfer full) (nullable): a new IDXGISwapChain1 or %NULL
* when failed to create swap chain with given @desc
*/
IDXGISwapChain1 *
gst_d3d11_device_create_swap_chain_for_hwnd (GstD3D11Device * device,
HWND hwnd, const DXGI_SWAP_CHAIN_DESC1 * desc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC * fullscreen_desc,
IDXGIOutput * output)
{
CreateSwapChainForHwndData data = { 0, };
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
data.swap_chain = NULL;
data.hwnd = hwnd;
data.desc = desc;
data.fullscreen_desc = fullscreen_desc;
data.output = output;
gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc)
gst_d3d11_device_create_swap_chain_for_hwnd_internal, &data);
return data.swap_chain;
}
#endif
static void
gst_d3d11_device_release_swap_chain_internal (GstD3D11Device * device,
IDXGISwapChain * swap_chain)

View file

@ -90,6 +90,14 @@ D3D_FEATURE_LEVEL gst_d3d11_device_get_chosen_feature_level (GstD3D11Device
IDXGISwapChain * gst_d3d11_device_create_swap_chain (GstD3D11Device * device,
const DXGI_SWAP_CHAIN_DESC * desc);
#if (DXGI_HEADER_VERSION >= 2)
IDXGISwapChain1 * gst_d3d11_device_create_swap_chain_for_hwnd (GstD3D11Device * device,
HWND hwnd,
const DXGI_SWAP_CHAIN_DESC1 * desc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC * fullscreen_desc,
IDXGIOutput * output);
#endif
void gst_d3d11_device_release_swap_chain (GstD3D11Device * device,
IDXGISwapChain * swap_chain);

View file

@ -1010,6 +1010,7 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height,
GstCaps *render_caps;
MakeWindowAssociationData mwa_data = { 0, };
UINT swapchain_flags = 0;
DXGI_SWAP_EFFECT swap_effect = DXGI_SWAP_EFFECT_DISCARD;
#if (DXGI_HEADER_VERSION >= 5)
gboolean have_cll = FALSE;
gboolean have_mastering = FALSE;
@ -1099,6 +1100,10 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height,
GST_DEBUG_OBJECT (window, "DXGI 1.5 interface is available");
swapchain4_available = TRUE;
/* For non-DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 color space support,
* DXGI_SWAP_EFFECT_FLIP_DISCARD instead of DXGI_SWAP_EFFECT_DISCARD */
swap_effect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
g_object_get (window->device, "allow-tearing", &allow_tearing, NULL);
if (allow_tearing) {
GST_DEBUG_OBJECT (window, "device support tearning");
@ -1135,32 +1140,63 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height,
window->width = width;
window->height = height;
/* we will get client area at on_resize */
desc.BufferDesc.Width = 0;
desc.BufferDesc.Height = 0;
/* don't care refresh rate */
desc.BufferDesc.RefreshRate.Numerator = 0;
desc.BufferDesc.RefreshRate.Denominator = 1;
desc.BufferDesc.Format = window->render_format->dxgi_format;
desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 2;
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
#if (DXGI_HEADER_VERSION >= 5)
/* For non-DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 color space support,
* DXGI_SWAP_EFFECT_FLIP_DISCARD instead of DXGI_SWAP_EFFECT_DISCARD */
if (swapchain4_available)
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
#endif
desc.OutputWindow = window->internal_win_id;
desc.Windowed = TRUE;
desc.Flags = swapchain_flags;
#if (DXGI_HEADER_VERSION >= 2)
if (!window->swap_chain) {
DXGI_SWAP_CHAIN_DESC1 desc1 = { 0, };
desc1.Width = 0;
desc1.Height = 0;
desc1.Format = window->render_format->dxgi_format;
/* FIXME: add support stereo */
desc1.Stereo = FALSE;
desc1.SampleDesc.Count = 1;
desc1.SampleDesc.Quality = 0;
desc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc1.BufferCount = 2;
/* NOTE: for UWP app, this should be DXGI_SCALING_ASPECT_RATIO_STRETCH
* with CreateSwapChainForComposition or CreateSwapChainForCoreWindow */
desc1.Scaling = DXGI_SCALING_STRETCH;
window->swap_chain =
gst_d3d11_device_create_swap_chain (window->device, &desc);
/* scaling-stretch would break aspect-ratio so we prefer to use scaling-none,
* but Windows7 does not support this method */
if (gst_d3d11_is_windows_8_or_greater ())
desc1.Scaling = DXGI_SCALING_NONE;
desc1.SwapEffect = swap_effect;
/* FIXME: might need to define for ovelay composition */
desc1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
desc1.Flags = swapchain_flags;
window->swap_chain = (IDXGISwapChain *)
gst_d3d11_device_create_swap_chain_for_hwnd (window->device,
window->internal_win_id, &desc1, NULL, NULL);
if (!window->swap_chain) {
GST_WARNING_OBJECT (window, "Failed to create swapchain1");
}
}
#endif
if (!window->swap_chain) {
/* we will get client area at on_resize */
desc.BufferDesc.Width = 0;
desc.BufferDesc.Height = 0;
/* don't care refresh rate */
desc.BufferDesc.RefreshRate.Numerator = 0;
desc.BufferDesc.RefreshRate.Denominator = 1;
desc.BufferDesc.Format = window->render_format->dxgi_format;
desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 2;
desc.SwapEffect = swap_effect;
desc.OutputWindow = window->internal_win_id;
desc.Windowed = TRUE;
desc.Flags = swapchain_flags;
window->swap_chain =
gst_d3d11_device_create_swap_chain (window->device, &desc);
}
if (!window->swap_chain) {
GST_ERROR_OBJECT (window, "Cannot create swapchain");