display.cpp.inc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include <dirent.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. #include <va/va.h>
  10. # include <va/va_drm.h>
  11. #include "opencv2/core.hpp" // cv::format()
  12. namespace va {
  13. bool openDisplay();
  14. void closeDisplay();
  15. VADisplay display = NULL;
  16. bool initialized = false;
  17. #define VA_INTEL_PCI_DIR "/sys/bus/pci/devices"
  18. #define VA_INTEL_DRI_DIR "/dev/dri/"
  19. #define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03
  20. static unsigned readId(const char* devName, const char* idName);
  21. static int findAdapter(unsigned desiredVendorId);
  22. int drmfd = -1;
  23. class Directory
  24. {
  25. typedef int (*fsort)(const struct dirent**, const struct dirent**);
  26. public:
  27. Directory(const char* path)
  28. {
  29. dirEntries = 0;
  30. numEntries = scandir(path, &dirEntries, filterFunc, (fsort)alphasort);
  31. }
  32. ~Directory()
  33. {
  34. if (numEntries && dirEntries)
  35. {
  36. for (int i = 0; i < numEntries; ++i)
  37. free(dirEntries[i]);
  38. free(dirEntries);
  39. }
  40. }
  41. int count() const
  42. {
  43. return numEntries;
  44. }
  45. const struct dirent* operator[](int index) const
  46. {
  47. return ((dirEntries != 0) && (index >= 0) && (index < numEntries)) ? dirEntries[index] : 0;
  48. }
  49. protected:
  50. static int filterFunc(const struct dirent* dir)
  51. {
  52. if (!dir) return 0;
  53. if (!strcmp(dir->d_name, ".")) return 0;
  54. if (!strcmp(dir->d_name, "..")) return 0;
  55. return 1;
  56. }
  57. private:
  58. int numEntries;
  59. struct dirent** dirEntries;
  60. };
  61. static unsigned readId(const char* devName, const char* idName)
  62. {
  63. long int id = 0;
  64. std::string fileName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName);
  65. FILE* file = fopen(fileName.c_str(), "r");
  66. if (file)
  67. {
  68. char str[16] = "";
  69. if (fgets(str, sizeof(str), file))
  70. id = strtol(str, NULL, 16);
  71. fclose(file);
  72. }
  73. return (unsigned)id;
  74. }
  75. static int findAdapter(unsigned desiredVendorId)
  76. {
  77. int adapterIndex = -1;
  78. Directory dir(VA_INTEL_PCI_DIR);
  79. for (int i = 0; i < dir.count(); ++i)
  80. {
  81. const char* name = dir[i]->d_name;
  82. unsigned classId = readId(name, "class");
  83. if ((classId >> 16) == VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS)
  84. {
  85. unsigned vendorId = readId(name, "vendor");
  86. if (vendorId == desiredVendorId)
  87. {
  88. std::string subdirName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, name, "drm");
  89. Directory subdir(subdirName.c_str());
  90. for (int j = 0; j < subdir.count(); ++j)
  91. {
  92. if (!strncmp(subdir[j]->d_name, "card", 4))
  93. {
  94. adapterIndex = strtoul(subdir[j]->d_name + 4, NULL, 10);
  95. }
  96. }
  97. break;
  98. }
  99. }
  100. }
  101. return adapterIndex;
  102. }
  103. class NodeInfo
  104. {
  105. enum { NUM_NODES = 2 };
  106. public:
  107. NodeInfo(int adapterIndex)
  108. {
  109. const char* names[NUM_NODES] = { "renderD", "card" };
  110. int numbers[NUM_NODES];
  111. numbers[0] = adapterIndex+128;
  112. numbers[1] = adapterIndex;
  113. for (int i = 0; i < NUM_NODES; ++i)
  114. {
  115. paths[i] = cv::format("%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]);
  116. }
  117. }
  118. ~NodeInfo()
  119. {
  120. // nothing
  121. }
  122. int count() const
  123. {
  124. return NUM_NODES;
  125. }
  126. const char* path(int index) const
  127. {
  128. return ((index >= 0) && (index < NUM_NODES)) ? paths[index].c_str() : 0;
  129. }
  130. private:
  131. std::string paths[NUM_NODES];
  132. };
  133. static bool openDeviceIntel();
  134. static bool openDeviceGeneric();
  135. static bool openDeviceIntel()
  136. {
  137. const unsigned IntelVendorID = 0x8086;
  138. int adapterIndex = findAdapter(IntelVendorID);
  139. if (adapterIndex >= 0)
  140. {
  141. NodeInfo nodes(adapterIndex);
  142. for (int i = 0; i < nodes.count(); ++i)
  143. {
  144. drmfd = open(nodes.path(i), O_RDWR);
  145. if (drmfd >= 0)
  146. {
  147. display = vaGetDisplayDRM(drmfd);
  148. if (display)
  149. return true;
  150. close(drmfd);
  151. drmfd = -1;
  152. }
  153. }
  154. }
  155. return false;
  156. }
  157. static bool openDeviceGeneric()
  158. {
  159. static const char* device_paths[] = { "/dev/dri/renderD128", "/dev/dri/card0" };
  160. static const int num_devices = sizeof(device_paths) / sizeof(device_paths[0]);
  161. for (int i = 0; i < num_devices; ++i)
  162. {
  163. drmfd = open(device_paths[i], O_RDWR);
  164. if (drmfd >= 0)
  165. {
  166. display = vaGetDisplayDRM(drmfd);
  167. if (display)
  168. return true;
  169. close(drmfd);
  170. drmfd = -1;
  171. }
  172. }
  173. return false;
  174. }
  175. bool openDisplay()
  176. {
  177. if (!initialized)
  178. {
  179. drmfd = -1;
  180. display = 0;
  181. if (openDeviceIntel() || openDeviceGeneric())
  182. {
  183. int majorVersion = 0, minorVersion = 0;
  184. if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS)
  185. {
  186. initialized = true;
  187. return true;
  188. }
  189. close(drmfd);
  190. display = 0;
  191. drmfd = -1;
  192. }
  193. return false; // Can't open VA display
  194. }
  195. return true;
  196. }
  197. void closeDisplay()
  198. {
  199. if (initialized)
  200. {
  201. if (display)
  202. vaTerminate(display);
  203. if (drmfd >= 0)
  204. close(drmfd);
  205. display = 0;
  206. drmfd = -1;
  207. initialized = false;
  208. }
  209. }
  210. } // namespace va