d3d11window: Use allow-tearing mode if device supports it
authorSeungha Yang <seungha.yang@navercorp.com>
Tue, 17 Dec 2019 04:47:24 +0000 (13:47 +0900)
committerSeungha Yang <seungha.yang@navercorp.com>
Fri, 20 Dec 2019 02:15:12 +0000 (11:15 +0900)
As the recommendation from MS.

sys/d3d11/gstd3d11device.c
sys/d3d11/gstd3d11window.c
sys/d3d11/gstd3d11window.h

index b2739db..9f11e43 100644 (file)
@@ -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;
index d24b726..ddab50f 100644 (file)
@@ -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",
index fb33b9f..496e190 100644 (file)
@@ -108,6 +108,7 @@ struct _GstD3D11Window
   gboolean enable_navigation_events;
 
   GstBuffer *cached_buffer;
+  gboolean allow_tearing;
 };
 
 struct _GstD3D11WindowClass