-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathDrmDevice.cpp
122 lines (101 loc) · 3.1 KB
/
DrmDevice.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2019 Stephan Gerhold
#define LOG_TAG "drmfb-device"
#include <fcntl.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include "drm_unique_ptr.h"
#include "DrmDevice.h"
namespace android {
namespace hardware {
namespace graphics {
namespace composer {
namespace V2_1 {
namespace drmfb {
DrmDevice::DrmDevice(int fd) : mFd(fd), mHotplugThread(*this) {}
DrmDevice::DrmDevice(const std::string& path) : DrmDevice(open(path.c_str(), O_RDWR)) {
if (mFd < 0)
PLOG(ERROR) << "Failed to open DRM device (" << path << ")";
}
DrmDevice::DrmDevice()
: DrmDevice(base::GetProperty("hwc.drm.device", "/dev/dri/card0")) {}
DrmDisplay* DrmDevice::getConnectedDisplay(uint32_t connector) {
auto i = mDisplays.find(connector);
if (i == mDisplays.end()) {
return nullptr;
}
auto display = i->second.get();
return display->connected() ? display : nullptr;
}
uint32_t DrmDevice::reserveCrtc(unsigned pipe) {
auto mask = 1 << pipe;
if (pipe < mCrtcs.size() && !(mUsedCrtcs & mask)) {
mUsedCrtcs |= mask;
return mCrtcs[pipe];
}
return 0;
}
void DrmDevice::freeCrtc(unsigned pipe) {
if (pipe < mCrtcs.size()) {
mUsedCrtcs &= ~(1 << pipe);
}
}
bool DrmDevice::initialize() {
if (mFd < 0)
return false;
drm::mode::unique_res_ptr res{drmModeGetResources(mFd)};
if (!res) {
PLOG(ERROR) << "Failed to get DRM mode resources";
return false;
}
// Store the available CRTCs
mCrtcs.assign(res->crtcs, res->crtcs + res->count_crtcs);
// Create displays for each connector
for (auto i = 0; i < res->count_connectors; ++i) {
mDisplays.insert({res->connectors[i],
std::make_unique<DrmDisplay>(*this, res->connectors[i])});
}
return true;
}
void DrmDevice::update() {
// TODO: Add new (hotplug) connectors (mostly relevant for DP MST)
for (auto& p : mDisplays) {
p.second->update();
}
}
void DrmDevice::enable(DrmCallback *callback) {
update();
mCallback = callback;
// Attempt to report a "primary" (internal) display first
auto primary = std::find_if(mDisplays.begin(), mDisplays.end(),
[] (const auto& pair) {
return pair.second->connected() && pair.second->internal();
});
if (primary != mDisplays.end()) {
LOG(INFO) << "Reporting display " << *primary->second
<< " as primary display";
primary->second->report();
}
for (auto i = mDisplays.begin(), end = mDisplays.end(); i != end; ++i) {
if (i == primary)
continue; // Primary display is already reported
auto display = i->second.get();
if (display->connected()) {
display->report();
}
}
mHotplugThread.enable();
}
void DrmDevice::disable() {
mHotplugThread.disable();
mCallback = nullptr;
for (auto& p : mDisplays) {
p.second->disable();
}
}
} // namespace drmfb
} // namespace V2_1
} // namespace composer
} // namespace graphics
} // namespace hardware
} // namespace android