xref: /third_party/mesa3d/src/tool/pps/pps_device.cc (revision bf215546)
1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2020 Collabora, Ltd.
3bf215546Sopenharmony_ci * Author: Antonio Caggiano <antonio.caggiano@collabora.com>
4bf215546Sopenharmony_ci * Author: Rohan Garg <rohan.garg@collabora.com>
5bf215546Sopenharmony_ci * Author: Robert Beckett <bob.beckett@collabora.com>
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT
8bf215546Sopenharmony_ci */
9bf215546Sopenharmony_ci
10bf215546Sopenharmony_ci#include "pps_device.h"
11bf215546Sopenharmony_ci
12bf215546Sopenharmony_ci#include <cassert>
13bf215546Sopenharmony_ci#include <fcntl.h>
14bf215546Sopenharmony_ci#include <memory>
15bf215546Sopenharmony_ci#include <unistd.h>
16bf215546Sopenharmony_ci#include <xf86drm.h>
17bf215546Sopenharmony_ci
18bf215546Sopenharmony_cinamespace pps
19bf215546Sopenharmony_ci{
20bf215546Sopenharmony_ci#define MAX_DRM_DEVICES 64
21bf215546Sopenharmony_ci
22bf215546Sopenharmony_ciuint32_t DrmDevice::device_count()
23bf215546Sopenharmony_ci{
24bf215546Sopenharmony_ci   drmDevicePtr devices[MAX_DRM_DEVICES] = {};
25bf215546Sopenharmony_ci   int num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES);
26bf215546Sopenharmony_ci   drmFreeDevices(devices, num_devices);
27bf215546Sopenharmony_ci   return static_cast<uint32_t>(num_devices);
28bf215546Sopenharmony_ci}
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci/// @return The name of a DRM device, empty string in case of error
31bf215546Sopenharmony_cistd::string query_drm_name(const int fd)
32bf215546Sopenharmony_ci{
33bf215546Sopenharmony_ci   assert(fd && "Failed to query DrmDevice: invalid fd");
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci   std::string name = "";
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci   if (drmVersionPtr version = drmGetVersion(fd)) {
38bf215546Sopenharmony_ci      name = std::string(version->name, version->name_len);
39bf215546Sopenharmony_ci      drmFreeVersion(version);
40bf215546Sopenharmony_ci   }
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci   return name;
43bf215546Sopenharmony_ci}
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci/// @return A DRM device, nullopt in case of error
46bf215546Sopenharmony_cistd::optional<DrmDevice> create_drm_device(int fd, int32_t gpu_num)
47bf215546Sopenharmony_ci{
48bf215546Sopenharmony_ci   if (fd < 0 || gpu_num < 0) {
49bf215546Sopenharmony_ci      return std::nullopt;
50bf215546Sopenharmony_ci   }
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   // Try getting the name
53bf215546Sopenharmony_ci   std::string name = query_drm_name(fd);
54bf215546Sopenharmony_ci   if (name.empty()) {
55bf215546Sopenharmony_ci      return std::nullopt;
56bf215546Sopenharmony_ci   }
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   auto ret = DrmDevice();
59bf215546Sopenharmony_ci   ret.fd = fd;
60bf215546Sopenharmony_ci   ret.gpu_num = gpu_num;
61bf215546Sopenharmony_ci   ret.name = name;
62bf215546Sopenharmony_ci   return ret;
63bf215546Sopenharmony_ci}
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_cistd::vector<DrmDevice> DrmDevice::create_all()
66bf215546Sopenharmony_ci{
67bf215546Sopenharmony_ci   std::vector<DrmDevice> ret = {};
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   drmDevicePtr devices[MAX_DRM_DEVICES] = {};
70bf215546Sopenharmony_ci   int num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES);
71bf215546Sopenharmony_ci   if (num_devices <= 0) {
72bf215546Sopenharmony_ci      return ret;
73bf215546Sopenharmony_ci   }
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   for (int32_t gpu_num = 0; gpu_num < num_devices; gpu_num++) {
76bf215546Sopenharmony_ci      drmDevicePtr device = devices[gpu_num];
77bf215546Sopenharmony_ci      if ((device->available_nodes & (1 << DRM_NODE_RENDER))) {
78bf215546Sopenharmony_ci         int fd = open(device->nodes[DRM_NODE_RENDER], O_RDWR);
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci         // If it can create a device, push it into the vector
81bf215546Sopenharmony_ci         if (auto drm_device = create_drm_device(fd, gpu_num)) {
82bf215546Sopenharmony_ci            ret.emplace_back(std::move(drm_device.value()));
83bf215546Sopenharmony_ci         }
84bf215546Sopenharmony_ci      }
85bf215546Sopenharmony_ci   }
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   drmFreeDevices(devices, num_devices);
88bf215546Sopenharmony_ci   return ret;
89bf215546Sopenharmony_ci}
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_cistd::optional<DrmDevice> DrmDevice::create(int32_t gpu_num)
92bf215546Sopenharmony_ci{
93bf215546Sopenharmony_ci   std::optional<DrmDevice> ret = std::nullopt;
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   if (gpu_num < 0) {
96bf215546Sopenharmony_ci      return ret;
97bf215546Sopenharmony_ci   }
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   drmDevicePtr devices[MAX_DRM_DEVICES] = {};
100bf215546Sopenharmony_ci   int num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES);
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   if (num_devices > 0 && gpu_num < num_devices) {
103bf215546Sopenharmony_ci      drmDevicePtr device = devices[gpu_num];
104bf215546Sopenharmony_ci      int fd = open(device->nodes[DRM_NODE_RENDER], O_RDWR);
105bf215546Sopenharmony_ci      ret = create_drm_device(fd, gpu_num);
106bf215546Sopenharmony_ci   }
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   drmFreeDevices(devices, num_devices);
109bf215546Sopenharmony_ci   return ret;
110bf215546Sopenharmony_ci}
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ciDrmDevice::DrmDevice(DrmDevice &&other)
113bf215546Sopenharmony_ci   : fd {other.fd}
114bf215546Sopenharmony_ci   , gpu_num {other.gpu_num}
115bf215546Sopenharmony_ci   , name {std::move(other.name)}
116bf215546Sopenharmony_ci{
117bf215546Sopenharmony_ci   other.fd = -1;
118bf215546Sopenharmony_ci   other.gpu_num = -1;
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ciDrmDevice &DrmDevice::operator=(DrmDevice &&other)
122bf215546Sopenharmony_ci{
123bf215546Sopenharmony_ci   std::swap(fd, other.fd);
124bf215546Sopenharmony_ci   std::swap(gpu_num, other.gpu_num);
125bf215546Sopenharmony_ci   std::swap(name, other.name);
126bf215546Sopenharmony_ci   return *this;
127bf215546Sopenharmony_ci}
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ciDrmDevice::~DrmDevice()
130bf215546Sopenharmony_ci{
131bf215546Sopenharmony_ci   if (fd >= 0) {
132bf215546Sopenharmony_ci      close(fd);
133bf215546Sopenharmony_ci   }
134bf215546Sopenharmony_ci}
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ciDrmDevice::operator bool() const
137bf215546Sopenharmony_ci{
138bf215546Sopenharmony_ci   return !name.empty();
139bf215546Sopenharmony_ci}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci} // namespace pps
142