mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 16:08:51 +00:00
d3d11: d3d11device: Add gst_d3d11_device_new_{for_adapter_luid,wrapped}
* gst_d3d11_device_new_for_adapter_luid() Used for creating D3D11 device for a DXGI adapter (i.e., GPU) corresponding to a LUID (Locally Unique Identifier). This method can be useful for interop with other APIs such as Direct3D12, MediaFoundation, CUDA, etc. * gst_d3d11_device_new_wrapped() Allows creating a new GstD3D11Device object by using already configured ID3D11Device. This is conceptually equivalent to gst_gl_context_new_wrapped() Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1098>
This commit is contained in:
parent
d8eff2623d
commit
5ac7a21ef0
6 changed files with 668 additions and 253 deletions
|
@ -130,25 +130,27 @@ struct _GstD3D11DevicePrivate
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_debug_init (void)
|
debug_init_once (void)
|
||||||
{
|
{
|
||||||
|
static gsize init_once = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&init_once)) {
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug,
|
GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug,
|
||||||
"d3d11device", 0, "d3d11 device object");
|
"d3d11device", 0, "d3d11 device object");
|
||||||
#if defined(HAVE_D3D11SDKLAYERS_H) || defined(HAVE_DXGIDEBUG_H)
|
#if defined(HAVE_D3D11SDKLAYERS_H) || defined(HAVE_DXGIDEBUG_H)
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_d3d11_debug_layer_debug,
|
GST_DEBUG_CATEGORY_INIT (gst_d3d11_debug_layer_debug,
|
||||||
"d3d11debuglayer", 0, "native d3d11 and dxgi debug");
|
"d3d11debuglayer", 0, "native d3d11 and dxgi debug");
|
||||||
#endif
|
#endif
|
||||||
|
g_once_init_leave (&init_once, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define gst_d3d11_device_parent_class parent_class
|
#define gst_d3d11_device_parent_class parent_class
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstD3D11Device, gst_d3d11_device, GST_TYPE_OBJECT,
|
G_DEFINE_TYPE_WITH_CODE (GstD3D11Device, gst_d3d11_device, GST_TYPE_OBJECT,
|
||||||
G_ADD_PRIVATE (GstD3D11Device); do_debug_init ());
|
G_ADD_PRIVATE (GstD3D11Device); debug_init_once ());
|
||||||
|
|
||||||
static void gst_d3d11_device_set_property (GObject * object, guint prop_id,
|
|
||||||
const GValue * value, GParamSpec * pspec);
|
|
||||||
static void gst_d3d11_device_get_property (GObject * object, guint prop_id,
|
static void gst_d3d11_device_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
static void gst_d3d11_device_constructed (GObject * object);
|
|
||||||
static void gst_d3d11_device_dispose (GObject * object);
|
static void gst_d3d11_device_dispose (GObject * object);
|
||||||
static void gst_d3d11_device_finalize (GObject * object);
|
static void gst_d3d11_device_finalize (GObject * object);
|
||||||
|
|
||||||
|
@ -363,22 +365,17 @@ static void
|
||||||
gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
|
gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
GParamFlags rw_construct_only_flags =
|
|
||||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
||||||
G_PARAM_STATIC_STRINGS);
|
|
||||||
GParamFlags readable_flags =
|
GParamFlags readable_flags =
|
||||||
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
gobject_class->set_property = gst_d3d11_device_set_property;
|
|
||||||
gobject_class->get_property = gst_d3d11_device_get_property;
|
gobject_class->get_property = gst_d3d11_device_get_property;
|
||||||
gobject_class->constructed = gst_d3d11_device_constructed;
|
|
||||||
gobject_class->dispose = gst_d3d11_device_dispose;
|
gobject_class->dispose = gst_d3d11_device_dispose;
|
||||||
gobject_class->finalize = gst_d3d11_device_finalize;
|
gobject_class->finalize = gst_d3d11_device_finalize;
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_ADAPTER,
|
g_object_class_install_property (gobject_class, PROP_ADAPTER,
|
||||||
g_param_spec_uint ("adapter", "Adapter",
|
g_param_spec_uint ("adapter", "Adapter",
|
||||||
"DXGI Adapter index for creating device",
|
"DXGI Adapter index for creating device",
|
||||||
0, G_MAXUINT32, DEFAULT_ADAPTER, rw_construct_only_flags));
|
0, G_MAXUINT32, DEFAULT_ADAPTER, readable_flags));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
|
g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
|
||||||
g_param_spec_uint ("device-id", "Device Id",
|
g_param_spec_uint ("device-id", "Device Id",
|
||||||
|
@ -396,15 +393,10 @@ gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
|
||||||
g_param_spec_string ("description", "Description",
|
g_param_spec_string ("description", "Description",
|
||||||
"Human readable device description", NULL, readable_flags));
|
"Human readable device description", NULL, readable_flags));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_CREATE_FLAGS,
|
|
||||||
g_param_spec_uint ("create-flags", "Create flags",
|
|
||||||
"D3D11_CREATE_DEVICE_FLAG flags used for D3D11CreateDevice",
|
|
||||||
0, G_MAXUINT32, DEFAULT_CREATE_FLAGS, rw_construct_only_flags));
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_ADAPTER_LUID,
|
g_object_class_install_property (gobject_class, PROP_ADAPTER_LUID,
|
||||||
g_param_spec_int64 ("adapter-luid", "Adapter LUID",
|
g_param_spec_int64 ("adapter-luid", "Adapter LUID",
|
||||||
"DXGI Adapter LUID (Locally Unique Identifier) of created device",
|
"DXGI Adapter LUID (Locally Unique Identifier) of created device",
|
||||||
0, G_MAXINT64, 0, readable_flags));
|
G_MININT64, G_MAXINT64, 0, readable_flags));
|
||||||
|
|
||||||
gst_d3d11_memory_init_once ();
|
gst_d3d11_memory_init_once ();
|
||||||
}
|
}
|
||||||
|
@ -743,216 +735,6 @@ gst_d3d11_device_setup_format_table (GstD3D11Device * self)
|
||||||
g_assert (n_formats == GST_D3D11_N_FORMATS);
|
g_assert (n_formats == GST_D3D11_N_FORMATS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_d3d11_device_constructed (GObject * object)
|
|
||||||
{
|
|
||||||
GstD3D11Device *self = GST_D3D11_DEVICE (object);
|
|
||||||
GstD3D11DevicePrivate *priv = self->priv;
|
|
||||||
ComPtr < IDXGIAdapter1 > adapter;
|
|
||||||
ComPtr < IDXGIFactory1 > factory;
|
|
||||||
HRESULT hr;
|
|
||||||
UINT d3d11_flags = priv->create_flags;
|
|
||||||
|
|
||||||
static const D3D_FEATURE_LEVEL feature_levels[] = {
|
|
||||||
D3D_FEATURE_LEVEL_11_1,
|
|
||||||
D3D_FEATURE_LEVEL_11_0,
|
|
||||||
D3D_FEATURE_LEVEL_10_1,
|
|
||||||
D3D_FEATURE_LEVEL_10_0,
|
|
||||||
D3D_FEATURE_LEVEL_9_3,
|
|
||||||
D3D_FEATURE_LEVEL_9_2,
|
|
||||||
D3D_FEATURE_LEVEL_9_1
|
|
||||||
};
|
|
||||||
D3D_FEATURE_LEVEL selected_level;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self,
|
|
||||||
"Built with DXGI header version %d", GST_D3D11_DXGI_HEADER_VERSION);
|
|
||||||
|
|
||||||
#if HAVE_DXGIDEBUG_H
|
|
||||||
if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
|
|
||||||
GST_LEVEL_NONE) {
|
|
||||||
if (gst_d3d11_device_enable_dxgi_debug ()) {
|
|
||||||
IDXGIDebug *debug = NULL;
|
|
||||||
IDXGIInfoQueue *info_queue = NULL;
|
|
||||||
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"dxgi debug library was loaded");
|
|
||||||
hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS (&debug));
|
|
||||||
|
|
||||||
if (SUCCEEDED (hr)) {
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"IDXGIDebug interface available");
|
|
||||||
priv->dxgi_debug = debug;
|
|
||||||
|
|
||||||
hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS
|
|
||||||
(&info_queue));
|
|
||||||
if (SUCCEEDED (hr)) {
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"IDXGIInfoQueue interface available");
|
|
||||||
priv->dxgi_info_queue = info_queue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"couldn't load dxgi debug library");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
|
|
||||||
if (!gst_d3d11_result (hr, NULL)) {
|
|
||||||
GST_ERROR_OBJECT (self, "cannot create dxgi factory, hr: 0x%x", (guint) hr);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (factory->EnumAdapters1 (priv->adapter, &adapter) == DXGI_ERROR_NOT_FOUND) {
|
|
||||||
GST_DEBUG_OBJECT (self, "No adapter for index %d", priv->adapter);
|
|
||||||
goto out;
|
|
||||||
} else {
|
|
||||||
DXGI_ADAPTER_DESC1 desc;
|
|
||||||
|
|
||||||
hr = adapter->GetDesc1 (&desc);
|
|
||||||
if (SUCCEEDED (hr)) {
|
|
||||||
gchar *description = NULL;
|
|
||||||
gboolean is_hardware = FALSE;
|
|
||||||
gint64 adapter_luid;
|
|
||||||
|
|
||||||
/* DXGI_ADAPTER_FLAG_SOFTWARE is missing in dxgi.h of mingw */
|
|
||||||
if ((desc.Flags & 0x2) != 0x2) {
|
|
||||||
is_hardware = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter_luid = (((gint64) desc.AdapterLuid.HighPart) << 32) |
|
|
||||||
((gint64) desc.AdapterLuid.LowPart);
|
|
||||||
description = g_utf16_to_utf8 ((gunichar2 *) desc.Description,
|
|
||||||
-1, NULL, NULL, NULL);
|
|
||||||
GST_DEBUG_OBJECT (self,
|
|
||||||
"adapter index %d: D3D11 device vendor-id: 0x%04x, device-id: 0x%04x, "
|
|
||||||
"Flags: 0x%x, adapter-luid: %" G_GINT64_FORMAT ", %s",
|
|
||||||
priv->adapter, desc.VendorId, desc.DeviceId, desc.Flags, adapter_luid,
|
|
||||||
description);
|
|
||||||
|
|
||||||
priv->vendor_id = desc.VendorId;
|
|
||||||
priv->device_id = desc.DeviceId;
|
|
||||||
priv->hardware = is_hardware;
|
|
||||||
priv->description = description;
|
|
||||||
priv->adapter_luid = adapter_luid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if HAVE_D3D11SDKLAYERS_H
|
|
||||||
if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
|
|
||||||
GST_LEVEL_NONE) {
|
|
||||||
/* DirectX SDK should be installed on system for this */
|
|
||||||
if (gst_d3d11_device_enable_d3d11_debug ()) {
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"d3d11 debug library was loaded");
|
|
||||||
d3d11_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
|
||||||
} else {
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"couldn't load d3d11 debug library");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
|
||||||
NULL, d3d11_flags, feature_levels, G_N_ELEMENTS (feature_levels),
|
|
||||||
D3D11_SDK_VERSION, &priv->device, &selected_level, &priv->device_context);
|
|
||||||
|
|
||||||
if (FAILED (hr)) {
|
|
||||||
/* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
|
|
||||||
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
|
||||||
NULL, d3d11_flags, &feature_levels[1],
|
|
||||||
G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &priv->device,
|
|
||||||
&selected_level, &priv->device_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if D3D11_CREATE_DEVICE_DEBUG was enabled but couldn't create device,
|
|
||||||
* try it without the flag again */
|
|
||||||
if (FAILED (hr) && (d3d11_flags & D3D11_CREATE_DEVICE_DEBUG) ==
|
|
||||||
D3D11_CREATE_DEVICE_DEBUG) {
|
|
||||||
GST_WARNING_OBJECT (self, "Couldn't create d3d11 device with debug flag");
|
|
||||||
|
|
||||||
d3d11_flags &= ~D3D11_CREATE_DEVICE_DEBUG;
|
|
||||||
|
|
||||||
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
|
||||||
NULL, d3d11_flags, feature_levels, G_N_ELEMENTS (feature_levels),
|
|
||||||
D3D11_SDK_VERSION, &priv->device, &selected_level,
|
|
||||||
&priv->device_context);
|
|
||||||
|
|
||||||
if (FAILED (hr)) {
|
|
||||||
/* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
|
|
||||||
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
|
||||||
NULL, d3d11_flags, &feature_levels[1],
|
|
||||||
G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &priv->device,
|
|
||||||
&selected_level, &priv->device_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED (hr)) {
|
|
||||||
GST_DEBUG_OBJECT (self, "Selected feature level 0x%x", selected_level);
|
|
||||||
} else {
|
|
||||||
GST_INFO_OBJECT (self,
|
|
||||||
"cannot create d3d11 device for adapter index %d with flags 0x%x, "
|
|
||||||
"hr: 0x%x", priv->adapter, d3d11_flags, (guint) hr);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->factory = factory.Detach ();
|
|
||||||
|
|
||||||
#if HAVE_D3D11SDKLAYERS_H
|
|
||||||
if ((d3d11_flags & D3D11_CREATE_DEVICE_DEBUG) == D3D11_CREATE_DEVICE_DEBUG) {
|
|
||||||
ID3D11Debug *debug;
|
|
||||||
ID3D11InfoQueue *info_queue;
|
|
||||||
|
|
||||||
hr = priv->device->QueryInterface (IID_PPV_ARGS (&debug));
|
|
||||||
|
|
||||||
if (SUCCEEDED (hr)) {
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"D3D11Debug interface available");
|
|
||||||
priv->d3d11_debug = debug;
|
|
||||||
|
|
||||||
hr = priv->device->QueryInterface (IID_PPV_ARGS (&info_queue));
|
|
||||||
if (SUCCEEDED (hr)) {
|
|
||||||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
|
||||||
"ID3D11InfoQueue interface available");
|
|
||||||
priv->d3d11_info_queue = info_queue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Update final create flags here, since D3D11_CREATE_DEVICE_DEBUG
|
|
||||||
* might be added by us */
|
|
||||||
priv->create_flags = d3d11_flags;
|
|
||||||
|
|
||||||
gst_d3d11_device_setup_format_table (self);
|
|
||||||
|
|
||||||
out:
|
|
||||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_d3d11_device_set_property (GObject * object, guint prop_id,
|
|
||||||
const GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstD3D11Device *self = GST_D3D11_DEVICE (object);
|
|
||||||
GstD3D11DevicePrivate *priv = self->priv;
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_ADAPTER:
|
|
||||||
priv->adapter = g_value_get_uint (value);
|
|
||||||
break;
|
|
||||||
case PROP_CREATE_FLAGS:
|
|
||||||
priv->create_flags = g_value_get_uint (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_d3d11_device_get_property (GObject * object, guint prop_id,
|
gst_d3d11_device_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec)
|
GValue * value, GParamSpec * pspec)
|
||||||
|
@ -976,9 +758,6 @@ gst_d3d11_device_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_DESCRIPTION:
|
case PROP_DESCRIPTION:
|
||||||
g_value_set_string (value, priv->description);
|
g_value_set_string (value, priv->description);
|
||||||
break;
|
break;
|
||||||
case PROP_CREATE_FLAGS:
|
|
||||||
g_value_set_uint (value, priv->create_flags);
|
|
||||||
break;
|
|
||||||
case PROP_ADAPTER_LUID:
|
case PROP_ADAPTER_LUID:
|
||||||
g_value_set_int64 (value, priv->adapter_luid);
|
g_value_set_int64 (value, priv->adapter_luid);
|
||||||
break;
|
break;
|
||||||
|
@ -1045,36 +824,420 @@ gst_d3d11_device_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX,
|
||||||
|
DEVICE_CONSTRUCT_FOR_ADAPTER_LUID,
|
||||||
|
DEVICE_CONSTRUCT_WRAPPED,
|
||||||
|
} GstD3D11DeviceConstructType;
|
||||||
|
|
||||||
|
typedef struct _GstD3D11DeviceConstructData
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
guint adapter_index;
|
||||||
|
gint64 adapter_luid;
|
||||||
|
ID3D11Device *device;
|
||||||
|
} data;
|
||||||
|
GstD3D11DeviceConstructType type;
|
||||||
|
UINT create_flags;
|
||||||
|
} GstD3D11DeviceConstructData;
|
||||||
|
|
||||||
|
static HRESULT
|
||||||
|
_gst_d3d11_device_get_adapter (const GstD3D11DeviceConstructData * data,
|
||||||
|
IDXGIFactory1 * factory, guint * index, DXGI_ADAPTER_DESC * adapter_desc,
|
||||||
|
IDXGIAdapter1 ** dxgi_adapter)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
ComPtr < IDXGIAdapter1 > adapter1;
|
||||||
|
DXGI_ADAPTER_DESC desc;
|
||||||
|
|
||||||
|
switch (data->type) {
|
||||||
|
case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
|
||||||
|
{
|
||||||
|
hr = factory->EnumAdapters1 (data->data.adapter_index, &adapter1);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = adapter1->GetDesc (&desc);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
*index = data->data.adapter_index;
|
||||||
|
*adapter_desc = desc;
|
||||||
|
*dxgi_adapter = adapter1.Detach ();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
|
||||||
|
{
|
||||||
|
for (guint i = 0;; i++) {
|
||||||
|
gint64 luid;
|
||||||
|
|
||||||
|
adapter1 = nullptr;
|
||||||
|
|
||||||
|
hr = factory->EnumAdapters1 (i, &adapter1);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = adapter1->GetDesc (&desc);
|
||||||
|
if (FAILED (hr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
|
||||||
|
if (luid != data->data.adapter_luid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*index = i;
|
||||||
|
*adapter_desc = desc;
|
||||||
|
*dxgi_adapter = adapter1.Detach ();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
case DEVICE_CONSTRUCT_WRAPPED:
|
||||||
|
{
|
||||||
|
ComPtr < IDXGIDevice > dxgi_device;
|
||||||
|
ComPtr < IDXGIAdapter > adapter;
|
||||||
|
ID3D11Device *device = data->data.device;
|
||||||
|
guint luid;
|
||||||
|
|
||||||
|
hr = device->QueryInterface (IID_PPV_ARGS (&dxgi_device));
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = dxgi_device->GetAdapter (&adapter);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = adapter.As (&adapter1);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = adapter1->GetDesc (&desc);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
|
||||||
|
|
||||||
|
for (guint i = 0;; i++) {
|
||||||
|
DXGI_ADAPTER_DESC tmp_desc;
|
||||||
|
ComPtr < IDXGIAdapter1 > tmp;
|
||||||
|
|
||||||
|
hr = factory->EnumAdapters1 (i, &tmp);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = tmp->GetDesc (&tmp_desc);
|
||||||
|
if (FAILED (hr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (luid != gst_d3d11_luid_to_int64 (&tmp_desc.AdapterLuid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*index = i;
|
||||||
|
*adapter_desc = desc;
|
||||||
|
*dxgi_adapter = adapter1.Detach ();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_d3d11_device_setup_debug_layer (GstD3D11Device * self)
|
||||||
|
{
|
||||||
|
#if HAVE_DXGIDEBUG_H
|
||||||
|
if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
|
||||||
|
GST_LEVEL_ERROR) {
|
||||||
|
GstD3D11DevicePrivate *priv = self->priv;
|
||||||
|
|
||||||
|
if (gst_d3d11_device_enable_dxgi_debug ()) {
|
||||||
|
IDXGIDebug *debug = nullptr;
|
||||||
|
IDXGIInfoQueue *info_queue = nullptr;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
||||||
|
"dxgi debug library was loaded");
|
||||||
|
hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS (&debug));
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
||||||
|
"IDXGIDebug interface available");
|
||||||
|
priv->dxgi_debug = debug;
|
||||||
|
|
||||||
|
hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS
|
||||||
|
(&info_queue));
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
||||||
|
"IDXGIInfoQueue interface available");
|
||||||
|
priv->dxgi_info_queue = info_queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
||||||
|
"couldn't load dxgi debug library");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_D3D11SDKLAYERS_H
|
||||||
|
if ((self->priv->create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
|
||||||
|
GstD3D11DevicePrivate *priv = self->priv;
|
||||||
|
ID3D11Debug *debug;
|
||||||
|
ID3D11InfoQueue *info_queue;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = priv->device->QueryInterface (IID_PPV_ARGS (&debug));
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
||||||
|
"D3D11Debug interface available");
|
||||||
|
priv->d3d11_debug = debug;
|
||||||
|
|
||||||
|
hr = priv->device->QueryInterface (IID_PPV_ARGS (&info_queue));
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
||||||
|
"ID3D11InfoQueue interface available");
|
||||||
|
priv->d3d11_info_queue = info_queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstD3D11Device *
|
||||||
|
gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
|
||||||
|
{
|
||||||
|
ComPtr < IDXGIAdapter1 > adapter;
|
||||||
|
ComPtr < IDXGIFactory1 > factory;
|
||||||
|
ComPtr < ID3D11Device > device;
|
||||||
|
ComPtr < ID3D11DeviceContext > device_context;
|
||||||
|
HRESULT hr;
|
||||||
|
UINT create_flags;
|
||||||
|
guint adapter_index = 0;
|
||||||
|
DXGI_ADAPTER_DESC adapter_desc;
|
||||||
|
static const D3D_FEATURE_LEVEL feature_levels[] = {
|
||||||
|
D3D_FEATURE_LEVEL_11_1,
|
||||||
|
D3D_FEATURE_LEVEL_11_0,
|
||||||
|
D3D_FEATURE_LEVEL_10_1,
|
||||||
|
D3D_FEATURE_LEVEL_10_0,
|
||||||
|
D3D_FEATURE_LEVEL_9_3,
|
||||||
|
D3D_FEATURE_LEVEL_9_2,
|
||||||
|
D3D_FEATURE_LEVEL_9_1
|
||||||
|
};
|
||||||
|
D3D_FEATURE_LEVEL selected_level;
|
||||||
|
|
||||||
|
debug_init_once ();
|
||||||
|
|
||||||
|
hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
|
||||||
|
if (!gst_d3d11_result (hr, NULL)) {
|
||||||
|
GST_ERROR ("cannot create dxgi factory, hr: 0x%x", (guint) hr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_flags = 0;
|
||||||
|
if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
|
||||||
|
create_flags = data->create_flags;
|
||||||
|
#if HAVE_D3D11SDKLAYERS_H
|
||||||
|
if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
|
||||||
|
GST_LEVEL_ERROR) {
|
||||||
|
/* DirectX SDK should be installed on system for this */
|
||||||
|
if (gst_d3d11_device_enable_d3d11_debug ()) {
|
||||||
|
GST_CAT_INFO (gst_d3d11_debug_layer_debug,
|
||||||
|
"d3d11 debug library was loaded");
|
||||||
|
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
} else {
|
||||||
|
GST_CAT_INFO (gst_d3d11_debug_layer_debug,
|
||||||
|
"couldn't load d3d11 debug library");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure valid device handle */
|
||||||
|
if (data->type == DEVICE_CONSTRUCT_WRAPPED) {
|
||||||
|
ID3D11Device *external_device = data->data.device;
|
||||||
|
|
||||||
|
hr = external_device->QueryInterface (IID_PPV_ARGS (&device));
|
||||||
|
if (FAILED (hr)) {
|
||||||
|
GST_ERROR ("Not a valid external ID3D11Device handle");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->GetImmediateContext (&device_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = _gst_d3d11_device_get_adapter (data, factory.Get (), &adapter_index,
|
||||||
|
&adapter_desc, &adapter);
|
||||||
|
if (FAILED (hr)) {
|
||||||
|
GST_INFO ("Failed to get DXGI adapter");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
|
||||||
|
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
|
NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
|
||||||
|
D3D11_SDK_VERSION, &device, &selected_level, &device_context);
|
||||||
|
|
||||||
|
if (FAILED (hr)) {
|
||||||
|
/* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
|
||||||
|
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
|
NULL, create_flags, &feature_levels[1],
|
||||||
|
G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
|
||||||
|
&selected_level, &device_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if D3D11_CREATE_DEVICE_DEBUG was enabled but couldn't create device,
|
||||||
|
* try it without the flag again */
|
||||||
|
if (FAILED (hr) && (create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
|
||||||
|
create_flags &= ~D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
|
||||||
|
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
|
NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
|
||||||
|
D3D11_SDK_VERSION, &device, &selected_level, &device_context);
|
||||||
|
|
||||||
|
if (FAILED (hr)) {
|
||||||
|
/* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
|
||||||
|
hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
|
NULL, create_flags, &feature_levels[1],
|
||||||
|
G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
|
||||||
|
&selected_level, &device_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED (hr)) {
|
||||||
|
switch (data->type) {
|
||||||
|
case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
|
||||||
|
{
|
||||||
|
GST_INFO ("Failed to create d3d11 device for adapter index %d"
|
||||||
|
" with flags 0x%x, hr: 0x%x", data->data.adapter_index,
|
||||||
|
create_flags, (guint) hr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
|
||||||
|
{
|
||||||
|
GST_ERROR ("Failed to create d3d11 device for adapter luid %"
|
||||||
|
G_GINT64_FORMAT " with flags 0x%x, hr: 0x%x",
|
||||||
|
data->data.adapter_luid, create_flags, (guint) hr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstD3D11Device *self = nullptr;
|
||||||
|
GstD3D11DevicePrivate *priv;
|
||||||
|
|
||||||
|
self = (GstD3D11Device *) g_object_new (GST_TYPE_D3D11_DEVICE, nullptr);
|
||||||
|
gst_object_ref_sink (self);
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
|
||||||
|
priv->adapter = adapter_index;
|
||||||
|
priv->device = device.Detach ();
|
||||||
|
priv->device_context = device_context.Detach ();
|
||||||
|
priv->factory = factory.Detach ();
|
||||||
|
|
||||||
|
priv->vendor_id = adapter_desc.VendorId;
|
||||||
|
priv->device_id = adapter_desc.DeviceId;
|
||||||
|
priv->description = g_utf16_to_utf8 ((gunichar2 *) adapter_desc.Description,
|
||||||
|
-1, nullptr, nullptr, nullptr);
|
||||||
|
priv->adapter_luid = gst_d3d11_luid_to_int64 (&adapter_desc.AdapterLuid);
|
||||||
|
|
||||||
|
DXGI_ADAPTER_DESC1 desc1;
|
||||||
|
hr = adapter->GetDesc1 (&desc1);
|
||||||
|
|
||||||
|
/* DXGI_ADAPTER_FLAG_SOFTWARE is missing in dxgi.h of mingw */
|
||||||
|
if (SUCCEEDED (hr) && (desc1.Flags & 0x2) != 0x2)
|
||||||
|
priv->hardware = TRUE;
|
||||||
|
|
||||||
|
priv->create_flags = create_flags;
|
||||||
|
gst_d3d11_device_setup_format_table (self);
|
||||||
|
gst_d3d11_device_setup_debug_layer (self);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_d3d11_device_new:
|
* gst_d3d11_device_new:
|
||||||
* @adapter: the index of adapter for creating d3d11 device
|
* @adapter_index: the index of adapter for creating d3d11 device
|
||||||
* @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
|
* @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
|
||||||
*
|
*
|
||||||
* Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter
|
* Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_index
|
||||||
* or %NULL when failed to create D3D11 device with given adapter index.
|
* or %NULL when failed to create D3D11 device with given adapter index.
|
||||||
*
|
*
|
||||||
* Since: 1.20
|
* Since: 1.20
|
||||||
*/
|
*/
|
||||||
GstD3D11Device *
|
GstD3D11Device *
|
||||||
gst_d3d11_device_new (guint adapter, guint flags)
|
gst_d3d11_device_new (guint adapter_index, guint flags)
|
||||||
{
|
{
|
||||||
GstD3D11Device *device = NULL;
|
GstD3D11DeviceConstructData data;
|
||||||
GstD3D11DevicePrivate *priv;
|
|
||||||
|
|
||||||
device = (GstD3D11Device *)
|
data.data.adapter_index = adapter_index;
|
||||||
g_object_new (GST_TYPE_D3D11_DEVICE, "adapter", adapter,
|
data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX;
|
||||||
"create-flags", flags, NULL);
|
data.create_flags = flags;
|
||||||
|
|
||||||
priv = device->priv;
|
return gst_d3d11_device_new_internal (&data);
|
||||||
|
|
||||||
if (!priv->device || !priv->device_context) {
|
|
||||||
GST_DEBUG ("Cannot create d3d11 device with adapter %d", adapter);
|
|
||||||
gst_clear_object (&device);
|
|
||||||
} else {
|
|
||||||
gst_object_ref_sink (device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return device;
|
/**
|
||||||
|
* gst_d3d11_device_new_for_adapter_luid:
|
||||||
|
* @adapter_luid: an int64 representation of the DXGI adapter LUID
|
||||||
|
* @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
|
||||||
|
*
|
||||||
|
* Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_luid
|
||||||
|
* or %NULL when failed to create D3D11 device with given adapter luid.
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
GstD3D11Device *
|
||||||
|
gst_d3d11_device_new_for_adapter_luid (gint64 adapter_luid, guint flags)
|
||||||
|
{
|
||||||
|
GstD3D11DeviceConstructData data;
|
||||||
|
|
||||||
|
data.data.adapter_luid = adapter_luid;
|
||||||
|
data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_LUID;
|
||||||
|
data.create_flags = flags;
|
||||||
|
|
||||||
|
return gst_d3d11_device_new_internal (&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_d3d11_device_new_wrapped:
|
||||||
|
* @device: (transfer none): an existing ID3D11Device handle
|
||||||
|
*
|
||||||
|
* Returns: (transfer full) (nullable): a new #GstD3D11Device for @device
|
||||||
|
* or %NULL if an error occurred
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
GstD3D11Device *
|
||||||
|
gst_d3d11_device_new_wrapped (ID3D11Device * device)
|
||||||
|
{
|
||||||
|
GstD3D11DeviceConstructData data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (device != nullptr, nullptr);
|
||||||
|
|
||||||
|
data.data.device = device;
|
||||||
|
data.type = DEVICE_CONSTRUCT_WRAPPED;
|
||||||
|
data.create_flags = 0;
|
||||||
|
|
||||||
|
return gst_d3d11_device_new_internal (&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -59,9 +59,16 @@ GST_D3D11_API
|
||||||
GType gst_d3d11_device_get_type (void);
|
GType gst_d3d11_device_get_type (void);
|
||||||
|
|
||||||
GST_D3D11_API
|
GST_D3D11_API
|
||||||
GstD3D11Device * gst_d3d11_device_new (guint adapter,
|
GstD3D11Device * gst_d3d11_device_new (guint adapter_index,
|
||||||
guint flags);
|
guint flags);
|
||||||
|
|
||||||
|
GST_D3D11_API
|
||||||
|
GstD3D11Device * gst_d3d11_device_new_for_adapter_luid (gint64 adapter_luid,
|
||||||
|
guint flags);
|
||||||
|
|
||||||
|
GST_D3D11_API
|
||||||
|
GstD3D11Device * gst_d3d11_device_new_wrapped (ID3D11Device * device);
|
||||||
|
|
||||||
GST_D3D11_API
|
GST_D3D11_API
|
||||||
ID3D11Device * gst_d3d11_device_get_device_handle (GstD3D11Device * device);
|
ID3D11Device * gst_d3d11_device_get_device_handle (GstD3D11Device * device);
|
||||||
|
|
||||||
|
|
|
@ -367,6 +367,29 @@ gst_d3d11_ensure_element_data (GstElement * element, gint adapter,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_d3d11_luid_to_int64:
|
||||||
|
* @luid: A pointer to LUID struct
|
||||||
|
*
|
||||||
|
* Converts from a LUID to a 64-bit signed integer.
|
||||||
|
* See also Int64FromLuid method defined in
|
||||||
|
* windows.devices.display.core.interop.h Windows SDK header
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
gint64
|
||||||
|
gst_d3d11_luid_to_int64 (const LUID * luid)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER val;
|
||||||
|
|
||||||
|
g_return_val_if_fail (luid != nullptr, 0);
|
||||||
|
|
||||||
|
val.LowPart = luid->LowPart;
|
||||||
|
val.HighPart = luid->HighPart;
|
||||||
|
|
||||||
|
return val.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
|
_gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
|
||||||
const gchar * file, const gchar * function, gint line)
|
const gchar * file, const gchar * function, gint line)
|
||||||
|
|
|
@ -41,6 +41,9 @@ gboolean gst_d3d11_ensure_element_data (GstElement * element,
|
||||||
gint adapter,
|
gint adapter,
|
||||||
GstD3D11Device ** device);
|
GstD3D11Device ** device);
|
||||||
|
|
||||||
|
GST_D3D11_API
|
||||||
|
gint64 gst_d3d11_luid_to_int64 (const LUID * luid);
|
||||||
|
|
||||||
GST_D3D11_API
|
GST_D3D11_API
|
||||||
gboolean _gst_d3d11_result (HRESULT hr,
|
gboolean _gst_d3d11_result (HRESULT hr,
|
||||||
GstD3D11Device * device,
|
GstD3D11Device * device,
|
||||||
|
|
208
subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp
Normal file
208
subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 2021 Seungha Yang <seungha@centricular.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/check/gstcheck.h>
|
||||||
|
#include <gst/d3d11/gstd3d11.h>
|
||||||
|
#include <wrl.h>
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
using namespace Microsoft::WRL;
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
static gboolean have_multiple_adapters = FALSE;
|
||||||
|
|
||||||
|
GST_START_TEST (test_device_new)
|
||||||
|
{
|
||||||
|
GstD3D11Device *device = nullptr;
|
||||||
|
guint adapter_index = G_MAXINT;
|
||||||
|
|
||||||
|
device = gst_d3d11_device_new (0, 0);
|
||||||
|
fail_unless (GST_IS_D3D11_DEVICE (device));
|
||||||
|
|
||||||
|
g_object_get (device, "adapter", &adapter_index, nullptr);
|
||||||
|
fail_unless_equals_int (adapter_index, 0);
|
||||||
|
gst_clear_object (&device);
|
||||||
|
|
||||||
|
if (have_multiple_adapters) {
|
||||||
|
device = gst_d3d11_device_new (1, 0);
|
||||||
|
fail_unless (GST_IS_D3D11_DEVICE (device));
|
||||||
|
|
||||||
|
g_object_get (device, "adapter", &adapter_index, nullptr);
|
||||||
|
fail_unless_equals_int (adapter_index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_clear_object (&device);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_device_for_adapter_luid)
|
||||||
|
{
|
||||||
|
GstD3D11Device *device = nullptr;
|
||||||
|
HRESULT hr;
|
||||||
|
ComPtr < IDXGIAdapter1 > adapter;
|
||||||
|
ComPtr < IDXGIFactory1 > factory;
|
||||||
|
DXGI_ADAPTER_DESC desc;
|
||||||
|
guint adapter_index = G_MAXINT;
|
||||||
|
gint64 adapter_luid = 0;
|
||||||
|
gint64 luid;
|
||||||
|
|
||||||
|
hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
|
||||||
|
if (SUCCEEDED (hr))
|
||||||
|
hr = factory->EnumAdapters1 (0, &adapter);
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr))
|
||||||
|
hr = adapter->GetDesc (&desc);
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
|
||||||
|
device = gst_d3d11_device_new_for_adapter_luid (luid, 0);
|
||||||
|
fail_unless (GST_IS_D3D11_DEVICE (device));
|
||||||
|
|
||||||
|
g_object_get (device, "adapter", &adapter_index, "adapter-luid",
|
||||||
|
&adapter_luid, nullptr);
|
||||||
|
|
||||||
|
/* adapter_luid is corresponding to the first enumerated adapter,
|
||||||
|
* so adapter index should be zero here */
|
||||||
|
fail_unless_equals_int (adapter_index, 0);
|
||||||
|
fail_unless_equals_int64 (adapter_luid, luid);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_clear_object (&device);
|
||||||
|
adapter = nullptr;
|
||||||
|
|
||||||
|
if (have_multiple_adapters) {
|
||||||
|
if (SUCCEEDED (hr))
|
||||||
|
hr = factory->EnumAdapters1 (1, &adapter);
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr))
|
||||||
|
hr = adapter->GetDesc (&desc);
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
|
||||||
|
device = gst_d3d11_device_new_for_adapter_luid (luid, 0);
|
||||||
|
fail_unless (GST_IS_D3D11_DEVICE (device));
|
||||||
|
|
||||||
|
g_object_get (device, "adapter", &adapter_index, "adapter-luid",
|
||||||
|
&adapter_luid, nullptr);
|
||||||
|
|
||||||
|
fail_unless_equals_int (adapter_index, 1);
|
||||||
|
fail_unless_equals_int64 (adapter_luid, luid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_clear_object (&device);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_device_new_wrapped)
|
||||||
|
{
|
||||||
|
GstD3D11Device *device = nullptr;
|
||||||
|
GstD3D11Device *device_clone = nullptr;
|
||||||
|
ID3D11Device *device_handle, *device_handle_clone;
|
||||||
|
ID3D11DeviceContext *context_handle, *context_handle_clone;
|
||||||
|
guint adapter_index = 0;
|
||||||
|
guint index;
|
||||||
|
gint64 luid, luid_clone;
|
||||||
|
|
||||||
|
if (have_multiple_adapters)
|
||||||
|
adapter_index = 1;
|
||||||
|
|
||||||
|
device = gst_d3d11_device_new (adapter_index, 0);
|
||||||
|
fail_unless (GST_IS_D3D11_DEVICE (device));
|
||||||
|
|
||||||
|
device_handle = gst_d3d11_device_get_device_handle (device);
|
||||||
|
fail_unless (device_handle != nullptr);
|
||||||
|
|
||||||
|
context_handle = gst_d3d11_device_get_device_context_handle (device);
|
||||||
|
fail_unless (context_handle != nullptr);
|
||||||
|
|
||||||
|
g_object_get (device, "adapter", &index, "adapter-luid", &luid, nullptr);
|
||||||
|
fail_unless_equals_int (index, adapter_index);
|
||||||
|
|
||||||
|
device_clone = gst_d3d11_device_new_wrapped (device_handle);
|
||||||
|
fail_unless (GST_IS_D3D11_DEVICE (device_clone));
|
||||||
|
|
||||||
|
device_handle_clone = gst_d3d11_device_get_device_handle (device_clone);
|
||||||
|
fail_unless_equals_pointer (device_handle, device_handle_clone);
|
||||||
|
|
||||||
|
context_handle_clone =
|
||||||
|
gst_d3d11_device_get_device_context_handle (device_clone);
|
||||||
|
fail_unless_equals_pointer (context_handle, context_handle_clone);
|
||||||
|
|
||||||
|
g_object_get (device_clone,
|
||||||
|
"adapter", &index, "adapter-luid", &luid_clone, nullptr);
|
||||||
|
fail_unless_equals_int (index, adapter_index);
|
||||||
|
fail_unless_equals_int64 (luid, luid_clone);
|
||||||
|
|
||||||
|
gst_clear_object (&device);
|
||||||
|
gst_clear_object (&device_clone);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_d3d11_available (void)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
ComPtr < IDXGIAdapter1 > adapter;
|
||||||
|
ComPtr < IDXGIFactory1 > factory;
|
||||||
|
|
||||||
|
hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
|
||||||
|
if (FAILED (hr))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
hr = factory->EnumAdapters1 (0, &adapter);
|
||||||
|
if (FAILED (hr))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
adapter = nullptr;
|
||||||
|
hr = factory->EnumAdapters1 (1, &adapter);
|
||||||
|
if (SUCCEEDED (hr))
|
||||||
|
have_multiple_adapters = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Suite *
|
||||||
|
d3d11device_suite (void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create ("d3d11device");
|
||||||
|
TCase *tc_basic = tcase_create ("general");
|
||||||
|
|
||||||
|
suite_add_tcase (s, tc_basic);
|
||||||
|
|
||||||
|
if (!check_d3d11_available ())
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
tcase_add_test (tc_basic, test_device_new);
|
||||||
|
tcase_add_test (tc_basic, test_device_for_adapter_luid);
|
||||||
|
tcase_add_test (tc_basic, test_device_new_wrapped);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_CHECK_MAIN (d3d11device);
|
|
@ -92,6 +92,7 @@ base_tests = [
|
||||||
[['libs/vkcommandpool.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
[['libs/vkcommandpool.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
||||||
[['libs/vkimage.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
[['libs/vkimage.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
||||||
[['libs/vkinstance.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
[['libs/vkinstance.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
||||||
|
[['libs/d3d11device.cpp'], not gstd3d11_dep.found(), [gstd3d11_dep]],
|
||||||
]
|
]
|
||||||
|
|
||||||
# FIXME: unistd dependency, unstable or not tested yet on windows
|
# FIXME: unistd dependency, unstable or not tested yet on windows
|
||||||
|
@ -168,6 +169,16 @@ else
|
||||||
endif
|
endif
|
||||||
gst_plugin_scanner_path = join_paths(gst_plugin_scanner_dir, 'gst-plugin-scanner')
|
gst_plugin_scanner_path = join_paths(gst_plugin_scanner_dir, 'gst-plugin-scanner')
|
||||||
|
|
||||||
|
extra_args = []
|
||||||
|
# XXX: our MinGW 32bits toolchain complians when ComPtr is in use
|
||||||
|
if host_system == 'windows' and cc.get_id() != 'msvc'
|
||||||
|
mingw_args = cc.get_supported_arguments([
|
||||||
|
'-Wno-redundant-decls',
|
||||||
|
])
|
||||||
|
|
||||||
|
extra_args += mingw_args
|
||||||
|
endif
|
||||||
|
|
||||||
foreach t : base_tests
|
foreach t : base_tests
|
||||||
fnames = t.get(0)
|
fnames = t.get(0)
|
||||||
test_name = fnames[0].split('.').get(0).underscorify()
|
test_name = fnames[0].split('.').get(0).underscorify()
|
||||||
|
@ -187,8 +198,8 @@ foreach t : base_tests
|
||||||
if not skip_test
|
if not skip_test
|
||||||
exe = executable(test_name, fnames, extra_sources,
|
exe = executable(test_name, fnames, extra_sources,
|
||||||
include_directories : [configinc],
|
include_directories : [configinc],
|
||||||
c_args : gst_plugins_bad_args + test_defines,
|
c_args : gst_plugins_bad_args + test_defines + extra_args,
|
||||||
cpp_args : gst_plugins_bad_args + test_defines,
|
cpp_args : gst_plugins_bad_args + test_defines + extra_args,
|
||||||
dependencies : [libm] + test_deps + extra_deps,
|
dependencies : [libm] + test_deps + extra_deps,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue