From 23b47a7ec18cad75642d03d8d25c0662c78a4e7e Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 17 Dec 2019 13:47:24 +0900 Subject: [PATCH] d3d11window: Use allow-tearing mode if device supports it As the recommendation from MS. --- sys/d3d11/gstd3d11device.c | 20 ++++++++++++++++++++ sys/d3d11/gstd3d11window.c | 22 ++++++++++++++++++++-- sys/d3d11/gstd3d11window.h | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/sys/d3d11/gstd3d11device.c b/sys/d3d11/gstd3d11device.c index b2739db6d2..9f11e432c1 100644 --- a/sys/d3d11/gstd3d11device.c +++ b/sys/d3d11/gstd3d11device.c @@ -52,6 +52,7 @@ enum PROP_VENDER_ID, PROP_HARDWARE, PROP_DESCRIPTION, + PROP_ALLOW_TEARING, }; #define DEFAULT_ADAPTER 0 @@ -63,6 +64,7 @@ struct _GstD3D11DevicePrivate guint vender_id; gboolean hardware; gchar *description; + gboolean allow_tearing; ID3D11Device *device; ID3D11DeviceContext *device_context; @@ -186,6 +188,11 @@ gst_d3d11_device_class_init (GstD3D11DeviceClass * klass) "Human readable device description", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ALLOW_TEARING, + g_param_spec_boolean ("allow-tearing", "Allow tearing", + "Whether dxgi device supports allow-tearing feature or not", FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT"); } @@ -232,6 +239,16 @@ gst_d3d11_device_constructed (GObject * object) if (!gst_d3d11_result (hr)) { GST_INFO_OBJECT (self, "IDXGIFactory5 was unavailable"); factory = NULL; + } else { + BOOL allow_tearing; + + hr = IDXGIFactory5_CheckFeatureSupport ((IDXGIFactory5 *) factory, + DXGI_FEATURE_PRESENT_ALLOW_TEARING, (void *) &allow_tearing, + sizeof (allow_tearing)); + + priv->allow_tearing = SUCCEEDED (hr) && allow_tearing; + + hr = S_OK; } priv->factory_ver = GST_D3D11_DXGI_FACTORY_5; @@ -409,6 +426,9 @@ gst_d3d11_device_get_property (GObject * object, guint prop_id, case PROP_DESCRIPTION: g_value_set_string (value, priv->description); break; + case PROP_ALLOW_TEARING: + g_value_set_boolean (value, priv->allow_tearing); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/d3d11/gstd3d11window.c b/sys/d3d11/gstd3d11window.c index d24b726a46..ddab50fea3 100644 --- a/sys/d3d11/gstd3d11window.c +++ b/sys/d3d11/gstd3d11window.c @@ -1007,6 +1007,7 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, DXGI_SWAP_CHAIN_DESC desc = { 0, }; GstCaps *render_caps; MakeWindowAssociationData mwa_data = { 0, }; + UINT swapchain_flags = 0; #if defined(HAVE_DXGI_1_5_H) gboolean have_cll = FALSE; gboolean have_mastering = FALSE; @@ -1072,6 +1073,8 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, return FALSE; } + + window->allow_tearing = FALSE; #if defined(HAVE_DXGI_1_5_H) if (!gst_video_content_light_level_from_caps (&window->content_light_level, caps)) { @@ -1089,8 +1092,17 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, if (gst_d3d11_device_get_chosen_dxgi_factory_version (window->device) >= GST_D3D11_DXGI_FACTORY_5) { + gboolean allow_tearing = FALSE; + GST_DEBUG_OBJECT (window, "DXGI 1.5 interface is available"); swapchain4_available = TRUE; + + g_object_get (window->device, "allow-tearing", &allow_tearing, NULL); + if (allow_tearing) { + GST_DEBUG_OBJECT (window, "device support tearning"); + swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + window->allow_tearing = TRUE; + } } #endif @@ -1143,7 +1155,7 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, #endif desc.OutputWindow = window->internal_win_id; desc.Windowed = TRUE; - desc.Flags = 0; + desc.Flags = swapchain_flags; window->swap_chain = gst_d3d11_device_create_swap_chain (window->device, &desc); @@ -1307,6 +1319,7 @@ _present_on_device_thread (GstD3D11Device * device, FramePresentData * data) GstD3D11Window *self = data->window; ID3D11DeviceContext *device_context; HRESULT hr; + UINT present_flags = DXGI_PRESENT_DO_NOT_WAIT; device_context = gst_d3d11_device_get_device_context_handle (device); gst_buffer_replace (&self->cached_buffer, data->buffer); @@ -1333,8 +1346,13 @@ _present_on_device_thread (GstD3D11Device * device, FramePresentData * data) gst_d3d11_color_converter_update_rect (self->converter, &rect); gst_d3d11_color_converter_convert (self->converter, srv, &self->rtv); } +#ifdef HAVE_DXGI_1_5_H + if (self->allow_tearing) { + present_flags |= DXGI_PRESENT_ALLOW_TEARING; + } +#endif - hr = IDXGISwapChain_Present (self->swap_chain, 0, DXGI_PRESENT_DO_NOT_WAIT); + hr = IDXGISwapChain_Present (self->swap_chain, 0, present_flags); if (!gst_d3d11_result (hr)) { GST_WARNING_OBJECT (self, "Direct3D cannot present texture, hr: 0x%x", diff --git a/sys/d3d11/gstd3d11window.h b/sys/d3d11/gstd3d11window.h index fb33b9f63c..496e190c32 100644 --- a/sys/d3d11/gstd3d11window.h +++ b/sys/d3d11/gstd3d11window.h @@ -108,6 +108,7 @@ struct _GstD3D11Window gboolean enable_navigation_events; GstBuffer *cached_buffer; + gboolean allow_tearing; }; struct _GstD3D11WindowClass