Commit 9b7c81e1 authored by Vitaliy Ilichev's avatar Vitaliy Ilichev

[samples] fix drm drivers detection

Current mechanism to detect Intel drm drivers uses the following schema:
1) Walk through the list of PCI devices, get device properties
   (Vendor ID) and calculate number of PCI devices  that corresponds
   to ‘DISPLAY_CONTROLLER_CLASS’ (adapters_num)
2) Use adapters_num to get path to /dev/dri/cardN and /dev/dri/renderDN
   with checking for Vendor ID.
But this approach is not working in some cases. For example, if PCI device
is present but corresponding driver is not set up. So it can be attempt to
open wrong /dev/dri/renderN and /dev/dri/cardN  paths.

New approach is based on checking for /dev/dri/renderD<N> (N=0..15) with
drm request for driver name.
parent 65dd009e
...@@ -22,216 +22,91 @@ or https://software.intel.com/en-us/media-client-solutions-support. ...@@ -22,216 +22,91 @@ or https://software.intel.com/en-us/media-client-solutions-support.
#include "vaapi_utils_drm.h" #include "vaapi_utils_drm.h"
#include "vaapi_allocator.h" #include "vaapi_allocator.h"
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <stdexcept> #include <stdexcept>
#include "vaapi_utils_drm.h"
#include <drm_fourcc.h> #include <drm_fourcc.h>
#include <intel_bufmgr.h>
#define MFX_PCI_DIR "/sys/bus/pci/devices" constexpr mfxU32 MFX_DRI_MAX_NODES_NUM = 16;
#define MFX_DRI_DIR "/dev/dri/" constexpr mfxU32 MFX_DRI_RENDER_START_INDEX = 128;
#define MFX_PCI_DISPLAY_CONTROLLER_CLASS 0x03 constexpr mfxU32 MFX_DRI_CARD_START_INDEX = 0;
constexpr mfxU32 MFX_DRM_DRIVER_NAME_LEN = 4;
const char* MFX_DRM_INTEL_DRIVER_NAME = "i915";
const char* MFX_DRI_PATH = "/dev/dri/";
const char* MFX_DRI_NODE_RENDER = "renderD";
const char* MFX_DRI_NODE_CARD = "card";
struct mfx_disp_adapters int get_drm_driver_name(int fd, char *name, int name_size)
{ {
mfxU32 vendor_id; drm_version_t version = {};
mfxU32 device_id; version.name_len = name_size;
}; version.name = name;
return ioctl(fd, DRM_IOWR(0, drm_version), &version);
static int mfx_dir_filter(const struct dirent* dir_ent)
{
if (!dir_ent) return 0;
if (!strcmp(dir_ent->d_name, ".")) return 0;
if (!strcmp(dir_ent->d_name, "..")) return 0;
return 1;
} }
typedef int (*fsort)(const struct dirent**, const struct dirent**); int open_intel_adapter(int type)
static mfxU32 mfx_init_adapters(struct mfx_disp_adapters** p_adapters)
{ {
mfxU32 adapters_num = 0; std::string adapterPath = MFX_DRI_PATH;
int i = 0; char driverName[MFX_DRM_DRIVER_NAME_LEN + 1] = {};
struct mfx_disp_adapters* adapters = NULL; mfxU32 nodeIndex;
struct dirent** dir_entries = NULL;
int entries_num = scandir(MFX_PCI_DIR, &dir_entries, mfx_dir_filter, (fsort)alphasort); switch (type) {
case MFX_LIBVA_DRM:
char file_name[300] = {}; case MFX_LIBVA_AUTO:
char str[16] = {0}; adapterPath += MFX_DRI_NODE_RENDER;
FILE* file = NULL; nodeIndex = MFX_DRI_RENDER_START_INDEX;
break;
for (i = 0; i < entries_num; ++i) case MFX_LIBVA_DRM_MODESET:
{ adapterPath += MFX_DRI_NODE_CARD;
long int class_id = 0, vendor_id = 0, device_id = 0; nodeIndex = MFX_DRI_CARD_START_INDEX;
break;
if (!dir_entries[i]) default:
continue; throw std::invalid_argument("Wrong libVA backend type");
}
// obtaining device class id
snprintf(file_name, sizeof(file_name)/sizeof(file_name[0]), "%s/%s/%s", MFX_PCI_DIR, dir_entries[i]->d_name, "class");
file = fopen(file_name, "r");
if (file)
{
if (fgets(str, sizeof(str), file))
{
class_id = strtol(str, NULL, 16);
}
fclose(file);
if (MFX_PCI_DISPLAY_CONTROLLER_CLASS == (class_id >> 16))
{
// obtaining device vendor id
snprintf(file_name, sizeof(file_name)/sizeof(file_name[0]), "%s/%s/%s", MFX_PCI_DIR, dir_entries[i]->d_name, "vendor");
file = fopen(file_name, "r");
if (file)
{
if (fgets(str, sizeof(str), file))
{
vendor_id = strtol(str, NULL, 16);
}
fclose(file);
}
// obtaining device id
snprintf(file_name, sizeof(file_name)/sizeof(file_name[0]), "%s/%s/%s", MFX_PCI_DIR, dir_entries[i]->d_name, "device");
file = fopen(file_name, "r");
if (file)
{
if (fgets(str, sizeof(str), file))
{
device_id = strtol(str, NULL, 16);
}
fclose(file);
}
// adding valid adapter to the list
if (vendor_id && device_id)
{
struct mfx_disp_adapters* tmp_adapters = NULL;
tmp_adapters = (mfx_disp_adapters*)realloc(adapters, for (mfxU32 i = 0; i < MFX_DRI_MAX_NODES_NUM; ++i) {
(adapters_num+1)*sizeof(struct mfx_disp_adapters)); std::string curAdapterPath = adapterPath + std::to_string(nodeIndex + i);
if (tmp_adapters) int fd = open(curAdapterPath.c_str(), O_RDWR);
{ if (fd < 0) continue;
adapters = tmp_adapters;
adapters[adapters_num].vendor_id = vendor_id;
adapters[adapters_num].device_id = device_id;
++adapters_num; if (!get_drm_driver_name(fd, driverName, MFX_DRM_DRIVER_NAME_LEN) &&
} !strcmp(driverName, MFX_DRM_INTEL_DRIVER_NAME)) {
} return fd;
}
} }
free(dir_entries[i]); close(fd);
} }
if (entries_num) free(dir_entries);
if (p_adapters) *p_adapters = adapters;
return adapters_num; return -1;
} }
DRMLibVA::DRMLibVA(int type) DRMLibVA::DRMLibVA(int type)
: CLibVA(type) : CLibVA(type)
, m_fd(-1) , m_fd(-1)
{ {
const mfxU32 IntelVendorID = 0x8086;
//the first Intel adapter is only required now, the second - in the future
const mfxU32 numberOfRequiredIntelAdapter = 1;
const char nodesNames[][8] = {"renderD", "card"};
VAStatus va_res = VA_STATUS_SUCCESS;
mfxStatus sts = MFX_ERR_NONE; mfxStatus sts = MFX_ERR_NONE;
int major_version = 0, minor_version = 0;
mfx_disp_adapters* adapters = NULL; m_fd = open_intel_adapter(type);
int adapters_num = mfx_init_adapters(&adapters); if (m_fd < 0) throw std::range_error("Intel GPU was not found");
// Search for the required display adapter m_va_dpy = m_vadrmlib.vaGetDisplayDRM(m_fd);
int i = 0, nFoundAdapters = 0; if (m_va_dpy)
int nodesNumbers[] = {0,0};
while ((i < adapters_num) && (nFoundAdapters != numberOfRequiredIntelAdapter))
{
if (adapters[i].vendor_id == IntelVendorID)
{
nFoundAdapters++;
nodesNumbers[0] = i+128; //for render nodes
nodesNumbers[1] = i; //for card
}
i++;
}
if (adapters_num) free(adapters);
// If Intel adapter with specified number wasn't found, throws exception
if (nFoundAdapters != numberOfRequiredIntelAdapter)
throw std::range_error("The Intel adapter with a specified number wasn't found");
// Initialization of paths to the device nodes
char** adapterPaths = new char* [2];
for (int i=0; i<2; i++)
{ {
if ((i == 0) && (type == MFX_LIBVA_DRM_MODESET)) { int major_version = 0, minor_version = 0;
adapterPaths[i] = NULL; VAStatus va_res = m_libva.vaInitialize(m_va_dpy, &major_version, &minor_version);
continue; sts = va_to_mfx_status(va_res);
}
adapterPaths[i] = new char[sizeof(MFX_DRI_DIR) + sizeof(nodesNames[i]) + 3];
sprintf(adapterPaths[i], "%s%s%d", MFX_DRI_DIR, nodesNames[i], nodesNumbers[i]);
} }
else {
// Loading display. At first trying to open render nodes, then card. sts = MFX_ERR_NULL_PTR;
for (int i=0; i<2; i++)
{
if (!adapterPaths[i]) {
sts = MFX_ERR_UNSUPPORTED;
continue;
}
sts = MFX_ERR_NONE;
m_fd = open(adapterPaths[i], O_RDWR);
if (m_fd < 0) sts = MFX_ERR_NOT_INITIALIZED;
if (MFX_ERR_NONE == sts)
{
m_va_dpy = m_vadrmlib.vaGetDisplayDRM(m_fd);
if (!m_va_dpy)
{
close(m_fd);
sts = MFX_ERR_NULL_PTR;
}
}
if (MFX_ERR_NONE == sts)
{
va_res = m_libva.vaInitialize(m_va_dpy, &major_version, &minor_version);
sts = va_to_mfx_status(va_res);
if (MFX_ERR_NONE != sts)
{
close(m_fd);
m_fd = -1;
}
}
if (MFX_ERR_NONE == sts) break;
}
for (int i=0; i<2; i++)
{
delete [] adapterPaths[i];
} }
delete [] adapterPaths;
if (MFX_ERR_NONE != sts) if (MFX_ERR_NONE != sts)
{ {
if (m_va_dpy) if (m_va_dpy) m_libva.vaTerminate(m_va_dpy);
{ close(m_fd);
m_libva.vaTerminate(m_va_dpy); throw std::runtime_error("Loading of VA display was failed");
m_va_dpy=0;
}
if (m_fd >= 0)
{
close(m_fd);
m_fd=-1;
}
throw std::invalid_argument("Loading of VA display was failed");
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment