11 # include <va/va_drm.h>
13 #include "opencv2/core.hpp" // cv::format()
20 VADisplay display = NULL;
21 bool initialized = false;
23 #define VA_INTEL_PCI_DIR "/sys/bus/pci/devices"
24 #define VA_INTEL_DRI_DIR "/dev/dri/"
25 #define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03
27 static unsigned readId(const char* devName, const char* idName);
28 static int findAdapter(unsigned desiredVendorId);
34 typedef int (*fsort)(const struct dirent**, const struct dirent**);
36 Directory(const char* path)
39 numEntries = scandir(path, &dirEntries, filterFunc, (fsort)alphasort);
43 if (numEntries && dirEntries)
45 for (int i = 0; i < numEntries; ++i)
54 const struct dirent* operator[](int index) const
56 return ((dirEntries != 0) && (index >= 0) && (index < numEntries)) ? dirEntries[index] : 0;
59 static int filterFunc(const struct dirent* dir)
62 if (!strcmp(dir->d_name, ".")) return 0;
63 if (!strcmp(dir->d_name, "..")) return 0;
68 struct dirent** dirEntries;
71 static unsigned readId(const char* devName, const char* idName)
75 std::string fileName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName);
77 FILE* file = fopen(fileName.c_str(), "r");
81 if (fgets(str, sizeof(str), file))
82 id = strtol(str, NULL, 16);
88 static int findAdapter(unsigned desiredVendorId)
90 int adapterIndex = -1;
92 Directory dir(VA_INTEL_PCI_DIR);
94 for (int i = 0; i < dir.count(); ++i)
96 const char* name = dir[i]->d_name;
98 unsigned classId = readId(name, "class");
99 if ((classId >> 16) == VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS)
101 unsigned vendorId = readId(name, "vendor");
102 if (vendorId == desiredVendorId)
104 std::string subdirName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, name, "drm");
105 Directory subdir(subdirName.c_str());
106 for (int j = 0; j < subdir.count(); ++j)
108 if (!strncmp(subdir[j]->d_name, "card", 4))
110 adapterIndex = strtoul(subdir[j]->d_name + 4, NULL, 10);
123 enum { NUM_NODES = 2 };
125 NodeInfo(int adapterIndex)
127 const char* names[NUM_NODES] = { "renderD", "card" };
128 int numbers[NUM_NODES];
129 numbers[0] = adapterIndex+128;
130 numbers[1] = adapterIndex;
131 for (int i = 0; i < NUM_NODES; ++i)
133 paths[i] = cv::format("%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]);
144 const char* path(int index) const
146 return ((index >= 0) && (index < NUM_NODES)) ? paths[index].c_str() : 0;
149 std::string paths[NUM_NODES];
152 static bool openDeviceIntel();
153 static bool openDeviceGeneric();
155 static bool openDeviceIntel()
157 const unsigned IntelVendorID = 0x8086;
159 int adapterIndex = findAdapter(IntelVendorID);
160 if (adapterIndex >= 0)
162 NodeInfo nodes(adapterIndex);
164 for (int i = 0; i < nodes.count(); ++i)
166 drmfd = open(nodes.path(i), O_RDWR);
169 display = vaGetDisplayDRM(drmfd);
180 static bool openDeviceGeneric()
182 static const char* device_paths[] = { "/dev/dri/renderD128", "/dev/dri/card0" };
183 static const int num_devices = sizeof(device_paths) / sizeof(device_paths[0]);
185 for (int i = 0; i < num_devices; ++i)
187 drmfd = open(device_paths[i], O_RDWR);
190 display = vaGetDisplayDRM(drmfd);
207 if (openDeviceIntel() || openDeviceGeneric())
209 int majorVersion = 0, minorVersion = 0;
210 if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS)
219 return false; // Can't open VA display
229 vaTerminate(display);