dxgiscreencapsrc: Load HLSL compiler library using g_module_open
authorSeungha Yang <seungha@centricular.com>
Fri, 19 Jun 2020 13:14:29 +0000 (22:14 +0900)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 22 Jun 2020 14:36:16 +0000 (14:36 +0000)
Depending on OS version, available d3dcompiler library name is different.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1355>

sys/winscreencap/dxgicapture.c
sys/winscreencap/dxgicapture.h
sys/winscreencap/gstdxgiscreencapsrc.c
sys/winscreencap/gstdxgiscreencapsrc.h
sys/winscreencap/gstwinscreencap.c
sys/winscreencap/meson.build

index eb4060a..6d2de48 100644 (file)
@@ -24,6 +24,7 @@
 #include "dxgicapture.h"
 
 #include <d3dcompiler.h>
+#include <gmodule.h>
 
 GST_DEBUG_CATEGORY_EXTERN (gst_dxgi_screen_cap_src_debug);
 #define GST_CAT_DEFAULT gst_dxgi_screen_cap_src_debug
@@ -159,6 +160,51 @@ static void _set_verteces (DxgiCapture * self, vertex * verteces,
     RECT * dest_rect, const D3D11_TEXTURE2D_DESC * dst_desc, RECT * rect,
     const D3D11_TEXTURE2D_DESC * src_desc);
 
+static GModule *d3d_compiler_module = NULL;
+static pD3DCompile GstD3DCompileFunc = NULL;
+
+gboolean
+gst_dxgicap_shader_init (void)
+{
+  static volatile gsize _init = 0;
+  static const gchar *d3d_compiler_names[] = {
+    "d3dcompiler_47.dll",
+    "d3dcompiler_46.dll",
+    "d3dcompiler_45.dll",
+    "d3dcompiler_44.dll",
+    "d3dcompiler_43.dll",
+  };
+
+  if (g_once_init_enter (&_init)) {
+    gint i;
+    for (i = 0; i < G_N_ELEMENTS (d3d_compiler_names); i++) {
+      d3d_compiler_module =
+          g_module_open (d3d_compiler_names[i], G_MODULE_BIND_LAZY);
+
+      if (d3d_compiler_module) {
+        GST_INFO ("D3D compiler %s is available", d3d_compiler_names[i]);
+        if (!g_module_symbol (d3d_compiler_module, "D3DCompile",
+                (gpointer *) & GstD3DCompileFunc)) {
+          GST_ERROR ("Cannot load D3DCompile symbol from %s",
+              d3d_compiler_names[i]);
+          g_module_close (d3d_compiler_module);
+          d3d_compiler_module = NULL;
+          GstD3DCompileFunc = NULL;
+        } else {
+          break;
+        }
+      }
+    }
+
+    if (!GstD3DCompileFunc)
+      GST_WARNING ("D3D11 compiler library is unavailable");
+
+    g_once_init_leave (&_init, 1);
+  }
+
+  return ! !GstD3DCompileFunc;
+}
+
 DxgiCapture *
 dxgicap_new (HMONITOR monitor, GstDXGIScreenCapSrc * src)
 {
@@ -272,13 +318,15 @@ dxgicap_new (HMONITOR monitor, GstDXGIScreenCapSrc * src)
   }
 
   if (DXGI_MODE_ROTATION_IDENTITY != self->dupl_desc.Rotation) {
+    g_assert (GstD3DCompileFunc);
+
     /* For a rotated display, create a shader. */
-    hr = D3DCompile (STR_VERTEX_SHADER, sizeof (STR_VERTEX_SHADER),
+    hr = GstD3DCompileFunc (STR_VERTEX_SHADER, sizeof (STR_VERTEX_SHADER),
         NULL, NULL, NULL, "vs_main", "vs_4_0_level_9_1",
         0, 0, &vertex_shader_blob, NULL);
     HR_FAILED_GOTO (hr, D3DCompile, new_error);
 
-    hr = D3DCompile (STR_PIXEL_SHADER, sizeof (STR_PIXEL_SHADER),
+    hr = GstD3DCompileFunc (STR_PIXEL_SHADER, sizeof (STR_PIXEL_SHADER),
         NULL, NULL, NULL, "ps_main", "ps_4_0_level_9_1",
         0, 0, &pixel_shader_blob, NULL);
     HR_FAILED_GOTO (hr, D3DCompile, new_error);
index 2f6c520..f2967b6 100644 (file)
@@ -61,6 +61,8 @@ typedef struct _GstDXGIScreenCapSrc GstDXGIScreenCapSrc;
 
 typedef struct _DxgiCapture DxgiCapture;
 
+gboolean gst_dxgicap_shader_init (void);
+
 DxgiCapture *dxgicap_new (HMONITOR monitor, GstDXGIScreenCapSrc * src);
 void dxgicap_destory (DxgiCapture * _this);
 
index b416c9a..2ed902a 100644 (file)
@@ -43,6 +43,8 @@
 #include "config.h"
 #endif
 
+#include <windows.h>
+#include <versionhelpers.h>
 #include <gst/video/video.h>
 #include "gstdxgiscreencapsrc.h"
 #include "dxgicapture.h"
@@ -560,3 +562,20 @@ _get_hmonitor (GstDXGIScreenCapSrc * src)
   }
   return hmonitor;
 }
+
+void
+gst_dxgi_screen_cap_src_register (GstPlugin * plugin, GstRank rank)
+{
+  if (!IsWindows8OrGreater ()) {
+    GST_WARNING ("OS version is too old");
+    return;
+  }
+
+  if (!gst_dxgicap_shader_init ()) {
+    GST_WARNING ("Couldn't load HLS compiler");
+    return;
+  }
+
+  gst_element_register (plugin, "dxgiscreencapsrc",
+      rank, GST_TYPE_DXGI_SCREEN_CAP_SRC);
+}
index 4e5fa22..4c08c50 100644 (file)
@@ -28,5 +28,8 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (GstDXGIScreenCapSrc, gst_dxgi_screen_cap_src, GST,
     DXGI_SCREEN_CAP_SRC, GstPushSrc);
 
+void gst_dxgi_screen_cap_src_register (GstPlugin * plugin,
+                                       GstRank rank);
+
 G_END_DECLS
 #endif /* __GST_DXGI_SCREEN_CAP_SRC_H__ */
index f249396..9224cde 100644 (file)
@@ -25,7 +25,6 @@
 #include "gstdx9screencapsrc.h"
 
 #ifdef HAVE_DXGI_CAP
-#include <versionhelpers.h>
 #include "gstdxgiscreencapsrc.h"
 
 GST_DEBUG_CATEGORY (gst_dxgi_screen_cap_src_debug);
@@ -73,16 +72,7 @@ plugin_init (GstPlugin * plugin)
     return FALSE;
   }
 #ifdef HAVE_DXGI_CAP
-  if (IsWindows8OrGreater ()) {
-    GST_DEBUG_CATEGORY_INIT (gst_dxgi_screen_cap_src_debug,
-        "dxgiscreencapsrc", 0, "DirectX DXGI screen capture source");
-
-    /* dxgiscreencapsrc is needs Windows8 or later. */
-    if (!gst_element_register (plugin, "dxgiscreencapsrc",
-            GST_RANK_NONE, GST_TYPE_DXGI_SCREEN_CAP_SRC)) {
-      return FALSE;
-    }
-  }
+  gst_dxgi_screen_cap_src_register (plugin, GST_RANK_NONE);
 #endif
 
   return TRUE;
index de740dd..6700231 100644 (file)
@@ -17,7 +17,6 @@ d3d_dep = cc.find_library('d3d9', required : get_option('winscreencap'))
 gdi_dep = cc.find_library('gdi32', required : get_option('winscreencap'))
 d3d11_dep = cc.find_library('d3d11', required : false)
 dxgi_lib_dep = cc.find_library('dxgi', required : false)
-d3d_compile_dep = cc.find_library('d3dcompiler', required : false)
 windowscodecs_dep = cc.find_library('windowscodecs',  required : false)
 dxguid_dep = cc.find_library('dxguid',  required : false)
 
@@ -31,12 +30,12 @@ if not have_d3d9_h and get_option('winscreencap').enabled()
   error('winscreencap plugin enabled but d3d9.h not found')
 endif
 
-have_dxgi = d3d11_dep.found() and dxgi_lib_dep.found() and d3d_compile_dep.found() and windowscodecs_dep.found() and dxguid_dep.found() and have_d3d11_h and have_dxgi_h and have_d3dcompiler_h and have_versionhelpers_h
+have_dxgi = d3d11_dep.found() and dxgi_lib_dep.found() and windowscodecs_dep.found() and dxguid_dep.found() and have_d3d11_h and have_dxgi_h and have_d3dcompiler_h and have_versionhelpers_h
 
 if have_dxgi
   dxgi_c_args += ['-DHAVE_DXGI_CAP']
   dxgiscreencap_sources += ['dxgicapture.c', 'gstdxgiscreencapsrc.c']
-  dxgi_dep += [d3d11_dep, dxgi_lib_dep, d3d_compile_dep, windowscodecs_dep, dxguid_dep]
+  dxgi_dep += [gmodule_dep, d3d11_dep, dxgi_lib_dep, windowscodecs_dep, dxguid_dep]
 endif
 
 if d3d_dep.found() and gdi_dep.found() and have_d3d9_h