aboutsummaryrefslogtreecommitdiff
path: root/drm/ResourceManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drm/ResourceManager.cpp')
-rw-r--r--drm/ResourceManager.cpp131
1 files changed, 105 insertions, 26 deletions
diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp
index 46f77e4..c8235e9 100644
--- a/drm/ResourceManager.cpp
+++ b/drm/ResourceManager.cpp
@@ -21,35 +21,47 @@
#include <fcntl.h>
#include <sys/stat.h>
+#include <ctime>
#include <sstream>
#include "bufferinfo/BufferInfoGetter.h"
+#include "drm/DrmAtomicStateManager.h"
#include "drm/DrmDevice.h"
+#include "drm/DrmDisplayPipeline.h"
#include "drm/DrmPlane.h"
#include "utils/log.h"
#include "utils/properties.h"
namespace android {
-ResourceManager::ResourceManager() : num_displays_(0) {
+ResourceManager::ResourceManager(
+ PipelineToFrontendBindingInterface *p2f_bind_interface)
+ : frontend_interface_(p2f_bind_interface) {
+ if (uevent_listener_.Init() != 0) {
+ ALOGE("Can't initialize event listener");
+ }
}
ResourceManager::~ResourceManager() {
uevent_listener_.Exit();
}
-int ResourceManager::Init() {
+void ResourceManager::Init() {
+ if (initialized_) {
+ ALOGE("Already initialized");
+ return;
+ }
+
char path_pattern[PROPERTY_VALUE_MAX];
// Could be a valid path or it can have at the end of it the wildcard %
// which means that it will try open all devices until an error is met.
int path_len = property_get("vendor.hwc.drm.device", path_pattern,
"/dev/dri/card%");
- int ret = 0;
if (path_pattern[path_len - 1] != '%') {
- ret = AddDrmDevice(std::string(path_pattern));
+ AddDrmDevice(std::string(path_pattern));
} else {
path_pattern[path_len - 1] = '\0';
- for (int idx = 0; ret == 0; ++idx) {
+ for (int idx = 0;; ++idx) {
std::ostringstream path;
path << path_pattern << idx;
@@ -57,49 +69,116 @@ int ResourceManager::Init() {
if (stat(path.str().c_str(), &buf) != 0)
break;
- if (DrmDevice::IsKMSDev(path.str().c_str()))
- ret = AddDrmDevice(path.str());
+ if (DrmDevice::IsKMSDev(path.str().c_str())) {
+ AddDrmDevice(path.str());
+ }
}
}
- if (num_displays_ == 0) {
- ALOGE("Failed to initialize any displays");
- return ret != 0 ? -EINVAL : ret;
- }
-
char scale_with_gpu[PROPERTY_VALUE_MAX];
property_get("vendor.hwc.drm.scale_with_gpu", scale_with_gpu, "0");
scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1));
if (BufferInfoGetter::GetInstance() == nullptr) {
ALOGE("Failed to initialize BufferInfoGetter");
- return -EINVAL;
+ return;
}
- ret = uevent_listener_.Init();
- if (ret != 0) {
- ALOGE("Can't initialize event listener %d", ret);
- return ret;
+ uevent_listener_.RegisterHotplugHandler([this] {
+ const std::lock_guard<std::mutex> lock(GetMainLock());
+ UpdateFrontendDisplays();
+ });
+
+ UpdateFrontendDisplays();
+
+ initialized_ = true;
+}
+
+void ResourceManager::DeInit() {
+ if (!initialized_) {
+ ALOGE("Not initialized");
+ return;
}
- return 0;
+ uevent_listener_.RegisterHotplugHandler([] {});
+
+ DetachAllFrontendDisplays();
+ drms_.clear();
+
+ initialized_ = false;
}
int ResourceManager::AddDrmDevice(const std::string &path) {
auto drm = std::make_unique<DrmDevice>();
- int displays_added = 0;
- int ret = 0;
- std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_);
+ int ret = drm->Init(path.c_str());
drms_.push_back(std::move(drm));
- num_displays_ += displays_added;
return ret;
}
-DrmDevice *ResourceManager::GetDrmDevice(int display) {
+auto ResourceManager::GetTimeMonotonicNs() -> int64_t {
+ struct timespec ts {};
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ constexpr int64_t kNsInSec = 1000000000LL;
+ return int64_t(ts.tv_sec) * kNsInSec + int64_t(ts.tv_nsec);
+}
+
+void ResourceManager::UpdateFrontendDisplays() {
+ auto ordered_connectors = GetOrderedConnectors();
+
+ for (auto *conn : ordered_connectors) {
+ conn->UpdateModes();
+ bool connected = conn->IsConnected();
+ bool attached = attached_pipelines_.count(conn) != 0;
+
+ if (connected != attached) {
+ ALOGI("%s connector %s", connected ? "Attaching" : "Detaching",
+ conn->GetName().c_str());
+
+ if (connected) {
+ auto pipeline = DrmDisplayPipeline::CreatePipeline(*conn);
+ frontend_interface_->BindDisplay(pipeline.get());
+ attached_pipelines_[conn] = std::move(pipeline);
+ } else {
+ auto &pipeline = attached_pipelines_[conn];
+ frontend_interface_->UnbindDisplay(pipeline.get());
+ attached_pipelines_.erase(conn);
+ }
+ }
+ }
+ frontend_interface_->FinalizeDisplayBinding();
+}
+
+void ResourceManager::DetachAllFrontendDisplays() {
+ for (auto &p : attached_pipelines_) {
+ frontend_interface_->UnbindDisplay(p.second.get());
+ }
+ attached_pipelines_.clear();
+ frontend_interface_->FinalizeDisplayBinding();
+}
+
+auto ResourceManager::GetOrderedConnectors() -> std::vector<DrmConnector *> {
+ /* Put internal displays first then external to
+ * ensure Internal will take Primary slot
+ */
+
+ std::vector<DrmConnector *> ordered_connectors;
+
for (auto &drm : drms_) {
- if (drm->HandlesDisplay(display))
- return drm.get();
+ for (const auto &conn : drm->GetConnectors()) {
+ if (conn->IsInternal()) {
+ ordered_connectors.emplace_back(conn.get());
+ }
+ }
}
- return nullptr;
+
+ for (auto &drm : drms_) {
+ for (const auto &conn : drm->GetConnectors()) {
+ if (conn->IsExternal()) {
+ ordered_connectors.emplace_back(conn.get());
+ }
+ }
+ }
+
+ return ordered_connectors;
}
} // namespace android