drm_hwcomposer: Add resource manager support
Add a resource manager class that is responsible for detecting all
kms devices and allocates unique display numbers for every detected
display.
This is controlled by the value of hwc.drm.device property, if it ends
with a %, it will try to open minor devices until an error is detected.
E.g: /dev/dri/card%
Additionally, this will be used for finding an available writeback
connector that will be used for the flattening of the currently
displayed scene.
Signed-off-by: Alexandru Gheorghe <alexandru-cosmin.gheorghe@arm.com>
diff --git a/resourcemanager.cpp b/resourcemanager.cpp
new file mode 100644
index 0000000..80a67b7
--- /dev/null
+++ b/resourcemanager.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc-resource-manager"
+
+#include "resourcemanager.h"
+
+#include <cutils/properties.h>
+#include <log/log.h>
+#include <sstream>
+#include <string>
+
+namespace android {
+
+ResourceManager::ResourceManager() : num_displays_(0), gralloc_(NULL) {
+}
+
+int ResourceManager::Init() {
+ 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("hwc.drm.device", path_pattern, "/dev/dri/card0");
+ int ret = 0;
+ if (path_pattern[path_len - 1] != '%') {
+ ret = AddDrmDevice(std::string(path_pattern));
+ } else {
+ path_pattern[path_len - 1] = '\0';
+ for (int idx = 0; !ret; ++idx) {
+ std::ostringstream path;
+ path << path_pattern << idx;
+ ret = AddDrmDevice(path.str());
+ }
+ }
+
+ if (!num_displays_) {
+ ALOGE("Failed to initialize any displays");
+ return ret ? -EINVAL : ret;
+ }
+
+ return hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&gralloc_);
+}
+
+int ResourceManager::AddDrmDevice(std::string path) {
+ std::unique_ptr<DrmDevice> drm = std::make_unique<DrmDevice>();
+ int displays_added, ret;
+ std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_);
+ if (ret)
+ return ret;
+ std::shared_ptr<Importer> importer;
+ importer.reset(Importer::CreateInstance(drm.get()));
+ if (!importer) {
+ ALOGE("Failed to create importer instance");
+ return -ENODEV;
+ }
+ importers_.push_back(importer);
+ drms_.push_back(std::move(drm));
+ num_displays_ += displays_added;
+ return ret;
+}
+
+DrmDevice *ResourceManager::GetDrmDevice(int display) {
+ for (auto &drm : drms_) {
+ if (drm->HandlesDisplay(display))
+ return drm.get();
+ }
+ return NULL;
+}
+
+std::shared_ptr<Importer> ResourceManager::GetImporter(int display) {
+ for (unsigned int i = 0; i < drms_.size(); i++) {
+ if (drms_[i]->HandlesDisplay(display))
+ return importers_[i];
+ }
+ return NULL;
+}
+
+const gralloc_module_t *ResourceManager::gralloc() {
+ return gralloc_;
+}
+}